Eliminate todo!s

This commit is contained in:
Shunsuke Shibayama 2022-12-15 15:18:25 +09:00
parent e8e174b1e8
commit 800b6c43d9
8 changed files with 282 additions and 130 deletions

View file

@ -1,7 +1,6 @@
use std::mem; use std::mem;
use erg_common::dict::Dict; use erg_common::dict::Dict;
use erg_common::enum_unwrap;
use erg_common::error::Location; use erg_common::error::Location;
#[allow(unused)] #[allow(unused)]
use erg_common::log; use erg_common::log;
@ -10,6 +9,7 @@ use erg_common::shared::Shared;
use erg_common::traits::{Locational, Stream}; use erg_common::traits::{Locational, Stream};
use erg_common::vis::Field; use erg_common::vis::Field;
use erg_common::{dict, fn_name, option_enum_unwrap, set}; use erg_common::{dict, fn_name, option_enum_unwrap, set};
use erg_common::{enum_unwrap, fmt_vec};
use erg_common::{RcArray, Str}; use erg_common::{RcArray, Str};
use OpKind::*; use OpKind::*;
@ -34,6 +34,17 @@ use crate::error::{EvalError, EvalErrors, EvalResult, SingleEvalResult};
use super::instantiate::TyVarCache; use super::instantiate::TyVarCache;
use super::Variance; use super::Variance;
macro_rules! feature_error {
($ctx: expr, $loc: expr, $name: expr) => {
$crate::feature_error!(EvalErrors, EvalError, $ctx, $loc, $name)
};
}
macro_rules! unreachable_error {
($ctx: expr) => {
$crate::unreachable_error!(EvalErrors, EvalError, $ctx)
};
}
#[inline] #[inline]
pub fn type_from_token_kind(kind: TokenKind) -> Type { pub fn type_from_token_kind(kind: TokenKind) -> Type {
use TokenKind::*; use TokenKind::*;
@ -139,7 +150,9 @@ impl Context {
let obj = self.eval_const_expr(&attr.obj)?; let obj = self.eval_const_expr(&attr.obj)?;
Ok(self.eval_attr(obj, &attr.ident)?) Ok(self.eval_attr(obj, &attr.ident)?)
} }
_ => todo!(), other => {
feature_error!(self, other.loc(), &format!("eval {other}")).map_err(Into::into)
}
} }
} }
@ -260,7 +273,9 @@ impl Context {
fn call(&self, subr: ConstSubr, args: ValueArgs, loc: Location) -> EvalResult<ValueObj> { fn call(&self, subr: ConstSubr, args: ValueArgs, loc: Location) -> EvalResult<ValueObj> {
match subr { match subr {
ConstSubr::User(_user) => todo!(), ConstSubr::User(_user) => {
feature_error!(self, loc, "calling user-defined subroutines").map_err(Into::into)
}
ConstSubr::Builtin(builtin) => builtin.call(args, self).map_err(|mut e| { ConstSubr::Builtin(builtin) => builtin.call(args, self).map_err(|mut e| {
if e.0.loc.is_unknown() { if e.0.loc.is_unknown() {
e.0.loc = loc; e.0.loc = loc;
@ -387,7 +402,7 @@ impl Context {
fn eval_const_record(&self, record: &Record) -> EvalResult<ValueObj> { fn eval_const_record(&self, record: &Record) -> EvalResult<ValueObj> {
match record { match record {
Record::Normal(rec) => self.eval_const_normal_record(rec), Record::Normal(rec) => self.eval_const_normal_record(rec),
Record::Mixed(_rec) => unreachable!(), // should be desugared Record::Mixed(_rec) => unreachable_error!(self), // should be desugared
} }
} }
@ -408,9 +423,13 @@ impl Context {
let ident = match &attr.sig { let ident = match &attr.sig {
Signature::Var(var) => match &var.pat { Signature::Var(var) => match &var.pat {
VarPattern::Ident(ident) => Field::new(ident.vis(), ident.inspect().clone()), VarPattern::Ident(ident) => Field::new(ident.vis(), ident.inspect().clone()),
_ => todo!(), other => {
return feature_error!(self, other.loc(), &format!("record field: {other}"))
}
}, },
_ => todo!(), other => {
return feature_error!(self, other.loc(), &format!("record field: {other}"))
}
}; };
attrs.push((ident, elem)); attrs.push((ident, elem));
} }
@ -720,7 +739,8 @@ impl Context {
(lhs @ TyParam::FreeVar(_), rhs) => Ok(TyParam::bin(op, lhs, rhs)), (lhs @ TyParam::FreeVar(_), rhs) => Ok(TyParam::bin(op, lhs, rhs)),
(lhs, rhs @ TyParam::FreeVar(_)) => Ok(TyParam::bin(op, lhs, rhs)), (lhs, rhs @ TyParam::FreeVar(_)) => Ok(TyParam::bin(op, lhs, rhs)),
(e @ TyParam::Erased(_), _) | (_, e @ TyParam::Erased(_)) => Ok(e), (e @ TyParam::Erased(_), _) | (_, e @ TyParam::Erased(_)) => Ok(e),
(l, r) => todo!("{l:?} {op} {r:?}"), (l, r) => feature_error!(self, Location::Unknown, &format!("{l:?} {op} {r:?}"))
.map_err(Into::into),
} }
} }
@ -742,7 +762,7 @@ impl Context {
line!(), line!(),
))), ))),
Mutate => Ok(ValueObj::Mut(Shared::new(val))), Mutate => Ok(ValueObj::Mut(Shared::new(val))),
other => unreachable!("{other}"), _other => unreachable_error!(self),
} }
} }
@ -759,15 +779,19 @@ impl Context {
let tp = TyParam::FreeVar(fv); let tp = TyParam::FreeVar(fv);
Ok(tp) Ok(tp)
} else { } else {
todo!("{op} {fv}") feature_error!(self, Location::Unknown, &format!("{op} {fv}"))
} }
} }
other => todo!("{op} {other}"), other => feature_error!(self, Location::Unknown, &format!("{op} {other}")),
} }
} }
fn eval_app(&self, _name: Str, _args: Vec<TyParam>) -> EvalResult<TyParam> { fn eval_app(&self, name: Str, args: Vec<TyParam>) -> EvalResult<TyParam> {
todo!() feature_error!(
self,
Location::Unknown,
&format!("{name}({})", fmt_vec(&args))
)
} }
/// 量化変数などはそのまま返す /// 量化変数などはそのまま返す
@ -810,12 +834,7 @@ impl Context {
Ok(TyParam::Dict(new_dic)) Ok(TyParam::Dict(new_dic))
} }
TyParam::Type(_) | TyParam::Erased(_) | TyParam::Value(_) => Ok(p.clone()), TyParam::Type(_) | TyParam::Erased(_) | TyParam::Value(_) => Ok(p.clone()),
_other => Err(EvalErrors::from(EvalError::feature_error( _other => feature_error!(self, Location::Unknown, "???"),
self.cfg.input.clone(),
Location::Unknown,
"???",
self.caused_by(),
))),
} }
} }
@ -897,12 +916,7 @@ impl Context {
Ok(not(l, r)) Ok(not(l, r))
} }
other if other.is_monomorphic() => Ok(other), other if other.is_monomorphic() => Ok(other),
_other => Err(EvalErrors::from(EvalError::feature_error( _other => feature_error!(self, t_loc, "???"),
self.cfg.input.clone(),
t_loc,
"???",
self.caused_by(),
))),
} }
} }
@ -1252,7 +1266,7 @@ impl Context {
let t = enum_unwrap!(t, ValueObj::Type); // TODO: error handling let t = enum_unwrap!(t, ValueObj::Type); // TODO: error handling
return Ok(t.into_typ()); return Ok(t.into_typ());
} else { } else {
todo!() return feature_error!(self, t_loc, "??");
} }
} }
for (_class, methods) in ty_ctx.methods_list.iter() { for (_class, methods) in ty_ctx.methods_list.iter() {
@ -1267,7 +1281,7 @@ impl Context {
let t = enum_unwrap!(t, ValueObj::Type); // TODO: error handling let t = enum_unwrap!(t, ValueObj::Type); // TODO: error handling
return Ok(t.into_typ()); return Ok(t.into_typ());
} else { } else {
todo!() return feature_error!(self, t_loc, "??");
} }
} }
} }
@ -1332,7 +1346,7 @@ impl Context {
if let Some(t) = fv.get_type() { if let Some(t) = fv.get_type() {
Ok(t) Ok(t)
} else { } else {
todo!() // Type feature_error!(self, Location::Unknown, "??")
} }
} }
TyParam::Type(typ) => Ok(self.meta_type(&typ)), TyParam::Type(typ) => Ok(self.meta_type(&typ)),
@ -1361,13 +1375,21 @@ impl Context {
dict @ TyParam::Dict(_) => Ok(dict_t(dict)), dict @ TyParam::Dict(_) => Ok(dict_t(dict)),
TyParam::UnaryOp { op, val } => match op { TyParam::UnaryOp { op, val } => match op {
OpKind::Mutate => Ok(self.get_tp_t(&val)?.mutate()), OpKind::Mutate => Ok(self.get_tp_t(&val)?.mutate()),
_ => todo!(), _ => feature_error!(self, Location::Unknown, "??"),
}, },
TyParam::BinOp { op, lhs, rhs } => { TyParam::BinOp { op, lhs, rhs } => {
let op_name = op_to_name(op); let op_name = op_to_name(op);
todo!("get type: {op_name}({lhs}, {rhs})") feature_error!(
self,
Location::Unknown,
&format!("get type: {op_name}({lhs}, {rhs})")
)
} }
other => todo!("{other}"), other => feature_error!(
self,
Location::Unknown,
&format!("getting the type of {other}")
),
} }
} }
@ -1380,7 +1402,7 @@ impl Context {
if let Some(t) = fv.get_type() { if let Some(t) = fv.get_type() {
Ok(t) Ok(t)
} else { } else {
todo!() feature_error!(self, Location::Unknown, "??")
} }
} }
TyParam::Type(_) => Ok(Type::Type), TyParam::Type(_) => Ok(Type::Type),
@ -1395,7 +1417,11 @@ impl Context {
)) ))
}) })
} }
other => todo!("{other}"), other => feature_error!(
self,
Location::Unknown,
&format!("getting the class of {other}")
),
} }
} }

View file

@ -3,8 +3,9 @@ use std::mem;
use erg_common::enum_unwrap; use erg_common::enum_unwrap;
use crate::context::Context; use crate::context::Context;
use crate::feature_error;
use crate::ty::constructors::{and, mono}; use crate::ty::constructors::{and, mono};
use crate::ty::value::{EvalValueResult, GenTypeObj, TypeObj, ValueObj}; use crate::ty::value::{EvalValueError, EvalValueResult, GenTypeObj, TypeObj, ValueObj};
use crate::ty::ValueArgs; use crate::ty::ValueArgs;
use erg_common::error::{ErrorCore, ErrorKind, Location, SubMessage}; use erg_common::error::{ErrorCore, ErrorKind, Location, SubMessage};
use erg_common::style::{Color, StyledStr, StyledString, THEME}; use erg_common::style::{Color, StyledStr, StyledString, THEME};
@ -110,7 +111,12 @@ pub fn inheritable_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<
} }
Ok(ValueObj::Type(TypeObj::Generated(gen))) Ok(ValueObj::Type(TypeObj::Generated(gen)))
} }
_ => todo!(), other => feature_error!(
EvalValueError,
_ctx,
Location::Unknown,
&format!("Inheritable {other}")
),
} }
} }
@ -126,7 +132,7 @@ pub fn trait_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueOb
) )
})?; })?;
let Some(require) = require.as_type() else { let Some(require) = require.as_type() else {
let require = StyledString::new(&format!("{}", require), Some(ERR), None); let require = StyledString::new(&format!("{require}"), Some(ERR), None);
return Err(ErrorCore::new( return Err(ErrorCore::new(
vec![SubMessage::only_loc(Location::Unknown)], vec![SubMessage::only_loc(Location::Unknown)],
format!( format!(

View file

@ -29,9 +29,9 @@ use crate::error::{
binop_to_dname, readable_name, unaryop_to_dname, SingleTyCheckResult, TyCheckError, binop_to_dname, readable_name, unaryop_to_dname, SingleTyCheckResult, TyCheckError,
TyCheckErrors, TyCheckResult, TyCheckErrors, TyCheckResult,
}; };
use crate::hir;
use crate::varinfo::{Mutability, VarInfo, VarKind}; use crate::varinfo::{Mutability, VarInfo, VarKind};
use crate::AccessKind; use crate::AccessKind;
use crate::{feature_error, hir};
use RegistrationMode::*; use RegistrationMode::*;
use Visibility::*; use Visibility::*;
@ -940,8 +940,8 @@ impl Context {
self.substitute_call(obj, attr_name, &fv.crack(), pos_args, kw_args) self.substitute_call(obj, attr_name, &fv.crack(), pos_args, kw_args)
} }
Type::FreeVar(fv) => { Type::FreeVar(fv) => {
if let Some(_attr_name) = attr_name { if let Some(attr_name) = attr_name {
todo!() feature_error!(TyCheckErrors, TyCheckError, self, attr_name.loc(), "")
} else { } else {
let is_procedural = obj let is_procedural = obj
.show_acc() .show_acc()

View file

@ -19,12 +19,14 @@ use erg_parser::ast;
use erg_parser::token::TokenKind; use erg_parser::token::TokenKind;
use erg_parser::Parser; use erg_parser::Parser;
use crate::feature_error;
use crate::ty::constructors::*; use crate::ty::constructors::*;
use crate::ty::free::CanbeFree; use crate::ty::free::CanbeFree;
use crate::ty::free::{Constraint, HasLevel}; use crate::ty::free::{Constraint, HasLevel};
use crate::ty::typaram::{IntervalOp, TyParam, TyParamOrdering}; use crate::ty::typaram::{IntervalOp, TyParam, TyParamOrdering};
use crate::ty::value::ValueObj; use crate::ty::value::ValueObj;
use crate::ty::{HasType, ParamTy, Predicate, SubrKind, Type}; use crate::ty::{HasType, ParamTy, Predicate, SubrKind, Type};
use crate::type_feature_error;
use TyParamOrdering::*; use TyParamOrdering::*;
use Type::*; use Type::*;
@ -393,7 +395,7 @@ impl Context {
))) )))
} }
} }
other => todo!("{other}"), other => type_feature_error!(self, other.loc(), &format!("instantiating {other}")),
} }
} }
@ -579,7 +581,7 @@ impl Context {
self.get_similar_name(name.inspect()), self.get_similar_name(name.inspect()),
))) )))
} }
_ => todo!(), other => type_feature_error!(self, other.loc(), &format!("instantiating {other}")),
} }
} }
@ -592,7 +594,7 @@ impl Context {
match self.instantiate_const_expr(expr, erased_idx, tmp_tv_cache)? { match self.instantiate_const_expr(expr, erased_idx, tmp_tv_cache)? {
TyParam::Type(t) => Ok(*t), TyParam::Type(t) => Ok(*t),
TyParam::Value(ValueObj::Type(t)) => Ok(t.into_typ()), TyParam::Value(ValueObj::Type(t)) => Ok(t.into_typ()),
other => todo!("{other}"), other => type_feature_error!(self, expr.loc(), &format!("{other}")),
} }
} }
@ -621,13 +623,13 @@ impl Context {
pub(crate) fn instantiate_typespec( pub(crate) fn instantiate_typespec(
&self, &self,
spec: &TypeSpec, t_spec: &TypeSpec,
opt_decl_t: Option<&ParamTy>, opt_decl_t: Option<&ParamTy>,
tmp_tv_cache: &mut TyVarCache, tmp_tv_cache: &mut TyVarCache,
mode: RegistrationMode, mode: RegistrationMode,
not_found_is_qvar: bool, not_found_is_qvar: bool,
) -> TyCheckResult<Type> { ) -> TyCheckResult<Type> {
match spec { match t_spec {
TypeSpec::Infer(_) => Ok(free_var(self.level, Constraint::new_type_of(Type))), TypeSpec::Infer(_) => Ok(free_var(self.level, Constraint::new_type_of(Type))),
TypeSpec::PreDeclTy(predecl) => Ok(self.instantiate_predecl_t( TypeSpec::PreDeclTy(predecl) => Ok(self.instantiate_predecl_t(
predecl, predecl,
@ -830,7 +832,7 @@ impl Context {
)) ))
} }
TypeSpec::TypeApp { spec, args } => { TypeSpec::TypeApp { spec, args } => {
todo!("{spec}{args}") type_feature_error!(self, t_spec.loc(), &format!("instantiating {spec}{args}"))
} }
} }
} }
@ -850,7 +852,9 @@ impl Context {
TokenKind::SubtypeOf => Constraint::new_subtype_of( TokenKind::SubtypeOf => Constraint::new_subtype_of(
self.instantiate_typespec(&spec.t_spec, None, tv_cache, mode, true)?, self.instantiate_typespec(&spec.t_spec, None, tv_cache, mode, true)?,
), ),
TokenKind::SupertypeOf => todo!(), TokenKind::SupertypeOf => {
return type_feature_error!(self, spec.loc(), "supertype of");
}
TokenKind::Colon => Constraint::new_type_of(self.instantiate_typespec( TokenKind::Colon => Constraint::new_type_of(self.instantiate_typespec(
&spec.t_spec, &spec.t_spec,
None, None,
@ -862,10 +866,14 @@ impl Context {
}; };
let tv = named_free_var(lhs.inspect().clone(), self.level, constr); let tv = named_free_var(lhs.inspect().clone(), self.level, constr);
tv_cache.push_or_init_tyvar(lhs.inspect(), &tv); tv_cache.push_or_init_tyvar(lhs.inspect(), &tv);
Ok(())
} }
TypeBoundSpec::WithDefault { .. } => todo!(), TypeBoundSpec::WithDefault { .. } => type_feature_error!(
self,
bound.loc(),
"type boundary specification with default"
),
} }
Ok(())
} }
pub(crate) fn instantiate_ty_bounds( pub(crate) fn instantiate_ty_bounds(
@ -983,7 +991,7 @@ impl Context {
| TyParam::Mono(_) | TyParam::Mono(_)
| TyParam::FreeVar(_) | TyParam::FreeVar(_)
| TyParam::Erased(_)) => Ok(p), | TyParam::Erased(_)) => Ok(p),
other => todo!("{other}"), other => type_feature_error!(self, loc, &format!("instantiating {other}")),
} }
} }
@ -1134,7 +1142,7 @@ impl Context {
Ok(not(l, r)) Ok(not(l, r))
} }
other if other.is_monomorphic() => Ok(other), other if other.is_monomorphic() => Ok(other),
other => todo!("{other}"), other => type_feature_error!(self, loc, &format!("instantiating {other}")),
} }
} }

View file

@ -18,7 +18,7 @@ use crate::ty::{HasType, Predicate, Type};
// use crate::context::eval::SubstContext; // use crate::context::eval::SubstContext;
use crate::context::{Context, Variance}; use crate::context::{Context, Variance};
use crate::error::{SingleTyCheckResult, TyCheckError, TyCheckErrors, TyCheckResult}; use crate::error::{SingleTyCheckResult, TyCheckError, TyCheckErrors, TyCheckResult};
use crate::hir; use crate::{feature_error, hir, type_feature_error};
use Predicate as Pred; use Predicate as Pred;
use Type::*; use Type::*;
@ -674,7 +674,12 @@ impl Context {
self.resolve_expr_t(&mut arr.len)?; self.resolve_expr_t(&mut arr.len)?;
Ok(()) Ok(())
} }
_ => todo!(), other => feature_error!(
TyCheckError,
self,
other.loc(),
"resolve types of array comprehension"
),
}, },
hir::Expr::Tuple(tuple) => match tuple { hir::Expr::Tuple(tuple) => match tuple {
hir::Tuple::Normal(tup) => { hir::Tuple::Normal(tup) => {
@ -711,7 +716,12 @@ impl Context {
} }
Ok(()) Ok(())
} }
other => todo!("{other}"), other => feature_error!(
TyCheckError,
self,
other.loc(),
"resolve types of dict comprehension"
),
}, },
hir::Expr::Record(record) => { hir::Expr::Record(record) => {
for attr in record.attrs.iter_mut() { for attr in record.attrs.iter_mut() {
@ -1367,10 +1377,12 @@ impl Context {
} }
Ok(()) Ok(())
} }
(Type::FreeVar(lfv), _) if lfv.is_linked() => (Type::FreeVar(lfv), _) if lfv.is_linked() => {
self.sub_unify(&lfv.crack(), maybe_sup, loc, param_name), self.sub_unify(&lfv.crack(), maybe_sup, loc, param_name)
(_, Type::FreeVar(rfv)) if rfv.is_linked() => }
self.sub_unify(maybe_sub, &rfv.crack(), loc, param_name), (_, Type::FreeVar(rfv)) if rfv.is_linked() => {
self.sub_unify(maybe_sub, &rfv.crack(), loc, param_name)
}
(_, Type::FreeVar(rfv)) if rfv.is_unbound() => { (_, Type::FreeVar(rfv)) if rfv.is_unbound() => {
// NOTE: cannot `borrow_mut` because of cycle reference // NOTE: cannot `borrow_mut` because of cycle reference
let rfv_ref = unsafe { rfv.as_ptr().as_mut().unwrap() }; let rfv_ref = unsafe { rfv.as_ptr().as_mut().unwrap() };
@ -1477,15 +1489,24 @@ impl Context {
} }
(Type::Subr(lsub), Type::Subr(rsub)) => { (Type::Subr(lsub), Type::Subr(rsub)) => {
for lpt in lsub.default_params.iter() { for lpt in lsub.default_params.iter() {
if let Some(rpt) = rsub.default_params.iter().find(|rpt| rpt.name() == lpt.name()) { if let Some(rpt) = rsub
.default_params
.iter()
.find(|rpt| rpt.name() == lpt.name())
{
// contravariant // contravariant
self.sub_unify(rpt.typ(), lpt.typ(), loc, param_name)?; self.sub_unify(rpt.typ(), lpt.typ(), loc, param_name)?;
} else { todo!() } } else {
todo!()
}
} }
lsub.non_default_params.iter().zip(rsub.non_default_params.iter()).try_for_each(|(l, r)| { lsub.non_default_params
// contravariant .iter()
self.sub_unify(r.typ(), l.typ(), loc, param_name) .zip(rsub.non_default_params.iter())
})?; .try_for_each(|(l, r)| {
// contravariant
self.sub_unify(r.typ(), l.typ(), loc, param_name)
})?;
// covariant // covariant
self.sub_unify(&lsub.return_t, &rsub.return_t, loc, param_name)?; self.sub_unify(&lsub.return_t, &rsub.return_t, loc, param_name)?;
Ok(()) Ok(())
@ -1493,17 +1514,32 @@ impl Context {
(Type::Quantified(lsub), Type::Subr(rsub)) => { (Type::Quantified(lsub), Type::Subr(rsub)) => {
let Type::Subr(lsub) = lsub.as_ref() else { unreachable!() }; let Type::Subr(lsub) = lsub.as_ref() else { unreachable!() };
for lpt in lsub.default_params.iter() { for lpt in lsub.default_params.iter() {
if let Some(rpt) = rsub.default_params.iter().find(|rpt| rpt.name() == lpt.name()) { if let Some(rpt) = rsub
if lpt.typ().is_generalized() { continue; } .default_params
.iter()
.find(|rpt| rpt.name() == lpt.name())
{
if lpt.typ().is_generalized() {
continue;
}
// contravariant // contravariant
self.sub_unify(rpt.typ(), lpt.typ(), loc, param_name)?; self.sub_unify(rpt.typ(), lpt.typ(), loc, param_name)?;
} else { todo!() } } else {
todo!()
}
} }
lsub.non_default_params.iter().zip(rsub.non_default_params.iter()).try_for_each(|(l, r)| { lsub.non_default_params
if l.typ().is_generalized() { Ok(()) } .iter()
// contravariant .zip(rsub.non_default_params.iter())
else { self.sub_unify(r.typ(), l.typ(), loc, param_name) } .try_for_each(|(l, r)| {
})?; if l.typ().is_generalized() {
Ok(())
}
// contravariant
else {
self.sub_unify(r.typ(), l.typ(), loc, param_name)
}
})?;
// covariant // covariant
if !lsub.return_t.is_generalized() { if !lsub.return_t.is_generalized() {
self.sub_unify(&lsub.return_t, &rsub.return_t, loc, param_name)?; self.sub_unify(&lsub.return_t, &rsub.return_t, loc, param_name)?;
@ -1513,17 +1549,31 @@ impl Context {
(Type::Subr(lsub), Type::Quantified(rsub)) => { (Type::Subr(lsub), Type::Quantified(rsub)) => {
let Type::Subr(rsub) = rsub.as_ref() else { unreachable!() }; let Type::Subr(rsub) = rsub.as_ref() else { unreachable!() };
for lpt in lsub.default_params.iter() { for lpt in lsub.default_params.iter() {
if let Some(rpt) = rsub.default_params.iter().find(|rpt| rpt.name() == lpt.name()) { if let Some(rpt) = rsub
.default_params
.iter()
.find(|rpt| rpt.name() == lpt.name())
{
// contravariant // contravariant
if rpt.typ().is_generalized() { continue; } if rpt.typ().is_generalized() {
continue;
}
self.sub_unify(rpt.typ(), lpt.typ(), loc, param_name)?; self.sub_unify(rpt.typ(), lpt.typ(), loc, param_name)?;
} else { todo!() } } else {
todo!()
}
} }
lsub.non_default_params.iter().zip(rsub.non_default_params.iter()).try_for_each(|(l, r)| { lsub.non_default_params
// contravariant .iter()
if r.typ().is_generalized() { Ok(()) } .zip(rsub.non_default_params.iter())
else { self.sub_unify(r.typ(), l.typ(), loc, param_name) } .try_for_each(|(l, r)| {
})?; // contravariant
if r.typ().is_generalized() {
Ok(())
} else {
self.sub_unify(r.typ(), l.typ(), loc, param_name)
}
})?;
// covariant // covariant
if !rsub.return_t.is_generalized() { if !rsub.return_t.is_generalized() {
self.sub_unify(&lsub.return_t, &rsub.return_t, loc, param_name)?; self.sub_unify(&lsub.return_t, &rsub.return_t, loc, param_name)?;
@ -1547,9 +1597,14 @@ impl Context {
self.substitute_typarams(sub_def_t, maybe_sub); self.substitute_typarams(sub_def_t, maybe_sub);
for sup_trait in sub_ctx.super_traits.iter() { for sup_trait in sub_ctx.super_traits.iter() {
if self.supertype_of(maybe_sup, sup_trait) { if self.supertype_of(maybe_sup, sup_trait) {
for (l_maybe_sub, r_maybe_sup) in sup_trait.typarams().iter().zip(rps.iter()) { for (l_maybe_sub, r_maybe_sup) in
sup_trait.typarams().iter().zip(rps.iter())
{
self.sub_unify_tp(l_maybe_sub, r_maybe_sup, None, loc, false) self.sub_unify_tp(l_maybe_sub, r_maybe_sup, None, loc, false)
.map_err(|e| { self.undo_substitute_typarams(sub_def_t); e })?; .map_err(|e| {
self.undo_substitute_typarams(sub_def_t);
e
})?;
} }
self.undo_substitute_typarams(sub_def_t); self.undo_substitute_typarams(sub_def_t);
return Ok(()); return Ok(());
@ -1582,21 +1637,15 @@ impl Context {
self.sub_unify(maybe_sub, r, loc, param_name) self.sub_unify(maybe_sub, r, loc, param_name)
} }
// (X and Y) <: Z is valid when X <: Z or Y <: Z // (X and Y) <: Z is valid when X <: Z or Y <: Z
(Type::And(l, r), _) => { (Type::And(l, r), _) => self
self.sub_unify(l, maybe_sup, loc, param_name) .sub_unify(l, maybe_sup, loc, param_name)
.or_else(|_e| self.sub_unify(r, maybe_sup, loc, param_name)) .or_else(|_e| self.sub_unify(r, maybe_sup, loc, param_name)),
}
// X <: (Y or Z) is valid when X <: Y or X <: Z // X <: (Y or Z) is valid when X <: Y or X <: Z
(_, Type::Or(l, r)) => { (_, Type::Or(l, r)) => self
self.sub_unify(maybe_sub, l, loc, param_name) .sub_unify(maybe_sub, l, loc, param_name)
.or_else(|_e| self.sub_unify(maybe_sub, r, loc, param_name)) .or_else(|_e| self.sub_unify(maybe_sub, r, loc, param_name)),
} (_, Type::Ref(t)) => self.sub_unify(maybe_sub, t, loc, param_name),
(_, Type::Ref(t)) => { (_, Type::RefMut { before, .. }) => self.sub_unify(maybe_sub, before, loc, param_name),
self.sub_unify(maybe_sub, t, loc, param_name)
}
(_, Type::RefMut{ before, .. }) => {
self.sub_unify(maybe_sub, before, loc, param_name)
}
(Type::Proj { .. }, _) => todo!(), (Type::Proj { .. }, _) => todo!(),
(_, Type::Proj { .. }) => todo!(), (_, Type::Proj { .. }) => todo!(),
// TODO: Judgment for any number of preds // TODO: Judgment for any number of preds
@ -1616,16 +1665,22 @@ impl Context {
return Ok(()); return Ok(());
} }
todo!("{sub}, {sup}") todo!("{sub}, {sup}")
}, }
// {I: Int | I >= 1} <: Nat == {I: Int | I >= 0} // {I: Int | I >= 1} <: Nat == {I: Int | I >= 0}
(Type::Refinement(_), sup) => { (Type::Refinement(_), sup) => {
let sup = sup.clone().into_refinement(); let sup = sup.clone().into_refinement();
self.sub_unify(maybe_sub, &Type::Refinement(sup), loc, param_name) self.sub_unify(maybe_sub, &Type::Refinement(sup), loc, param_name)
}, }
(Type::Subr(_) | Type::Record(_), Type) => Ok(()), (Type::Subr(_) | Type::Record(_), Type) => Ok(()),
// REVIEW: correct? // REVIEW: correct?
(Type::Poly{ name, .. }, Type) if &name[..] == "Array" || &name[..] == "Tuple" => Ok(()), (Type::Poly { name, .. }, Type) if &name[..] == "Array" || &name[..] == "Tuple" => {
_ => todo!("{maybe_sub} can be a subtype of {maybe_sup}, but failed to semi-unify (or existential types are not supported)"), Ok(())
}
_ => type_feature_error!(
self,
loc,
&format!("{maybe_sub} can be a subtype of {maybe_sup}, but failed to semi-unify")
),
} }
} }
} }

View file

@ -20,6 +20,51 @@ use crate::context::Context;
use crate::hir::{Expr, Identifier, Signature}; use crate::hir::{Expr, Identifier, Signature};
use crate::ty::{HasType, Predicate, Type}; use crate::ty::{HasType, Predicate, Type};
/// `unreachable!(self: Context)`
#[macro_export]
macro_rules! unreachable_error {
($Strcs: ident, $Strc: ident, $ctx: expr) => {
Err($Strcs::from($Strc::unreachable(
$ctx.cfg.input.clone(),
fn_name!(),
line!(),
)))
};
($Strc: ident, $ctx: expr) => {
Err($Strc::unreachable(
$ctx.cfg.input.clone(),
fn_name!(),
line!(),
))
};
}
/// `feature_error!($Strc: struct, ctx: Context, loc: Location, name: &str)`
#[macro_export]
macro_rules! feature_error {
($Strcs: ident, $Strc: ident, $ctx: expr, $loc: expr, $name: expr) => {
Err($Strcs::from($Strc::feature_error(
$ctx.cfg.input.clone(),
$loc,
$name,
$ctx.caused_by(),
)))
};
($Strc: ident, $ctx: expr, $loc: expr, $name: expr) => {
Err($Strc::feature_error(
$ctx.cfg.input.clone(),
$loc,
$name,
$ctx.caused_by(),
))
};
}
#[macro_export]
macro_rules! type_feature_error {
($ctx: expr, $loc: expr, $name: expr) => {
feature_error!(TyCheckErrors, TyCheckError, $ctx, $loc, $name)
};
}
pub fn ordinal_num(n: usize) -> String { pub fn ordinal_num(n: usize) -> String {
match n.to_string().chars().last().unwrap() { match n.to_string().chars().last().unwrap() {
'1' => format!("{n}st"), '1' => format!("{n}st"),

View file

@ -40,28 +40,9 @@ use crate::mod_cache::SharedModuleCache;
use crate::reorder::Reorderer; use crate::reorder::Reorderer;
use crate::varinfo::{VarInfo, VarKind}; use crate::varinfo::{VarInfo, VarKind};
use crate::AccessKind; use crate::AccessKind;
use crate::{feature_error, unreachable_error};
use Visibility::*; use Visibility::*;
macro_rules! unreachable_error {
($self: ident) => {
Err(LowerErrors::from(LowerError::unreachable(
$self.cfg.input.clone(),
fn_name!(),
line!(),
)))
};
}
macro_rules! todo_error {
($self: ident, $loc: expr, $name: expr) => {
Err(LowerErrors::from(LowerError::feature_error(
$self.cfg.input.clone(),
$loc,
$name,
$self.ctx.caused_by(),
)))
};
}
/// Checks & infers types of an AST, and convert (lower) it into a HIR /// Checks & infers types of an AST, and convert (lower) it into a HIR
#[derive(Debug)] #[derive(Debug)]
pub struct ASTLowerer { pub struct ASTLowerer {
@ -337,7 +318,13 @@ impl ASTLowerer {
ast::Array::WithLength(arr) => { ast::Array::WithLength(arr) => {
Ok(hir::Array::WithLength(self.lower_array_with_length(arr)?)) Ok(hir::Array::WithLength(self.lower_array_with_length(arr)?))
} }
other => todo_error!(self, other.loc(), "array comprehension"), other => feature_error!(
LowerErrors,
LowerError,
self.ctx,
other.loc(),
"array comprehension"
),
} }
} }
@ -622,7 +609,13 @@ impl ASTLowerer {
log!(info "enter {}({dict})", fn_name!()); log!(info "enter {}({dict})", fn_name!());
match dict { match dict {
ast::Dict::Normal(set) => Ok(hir::Dict::Normal(self.lower_normal_dict(set)?)), ast::Dict::Normal(set) => Ok(hir::Dict::Normal(self.lower_normal_dict(set)?)),
other => todo_error!(self, other.loc(), "dict comprehension"), other => feature_error!(
LowerErrors,
LowerError,
self.ctx,
other.loc(),
"dict comprehension"
),
// ast::Dict::WithLength(set) => Ok(hir::Dict::WithLength(self.lower_dict_with_length(set)?)), // ast::Dict::WithLength(set) => Ok(hir::Dict::WithLength(self.lower_dict_with_length(set)?)),
} }
} }
@ -726,9 +719,15 @@ impl ASTLowerer {
let acc = hir::Accessor::Attr(hir::Attribute::new(obj, ident)); let acc = hir::Accessor::Attr(hir::Attribute::new(obj, ident));
Ok(acc) Ok(acc)
} }
ast::Accessor::TypeApp(t_app) => todo_error!(self, t_app.loc(), "type application"), ast::Accessor::TypeApp(t_app) => feature_error!(
LowerErrors,
LowerError,
self.ctx,
t_app.loc(),
"type application"
),
// TupleAttr, Subscr are desugared // TupleAttr, Subscr are desugared
_ => unreachable!(), _ => unreachable_error!(LowerErrors, LowerError, self.ctx),
} }
} }
@ -1193,7 +1192,7 @@ impl ASTLowerer {
let body = hir::DefBody::new(body.op, block, body.id); let body = hir::DefBody::new(body.op, block, body.id);
Ok(hir::Def::new(hir::Signature::Subr(sig), body)) Ok(hir::Def::new(hir::Signature::Subr(sig), body))
} }
_ => unreachable_error!(self), _ => unreachable_error!(LowerErrors, LowerError, self),
} }
} }
@ -1217,7 +1216,7 @@ impl ASTLowerer {
)?, )?,
tasc.t_spec.loc(), tasc.t_spec.loc(),
), ),
_ => return unreachable_error!(self), _ => return unreachable_error!(LowerErrors, LowerError, self),
}; };
( (
self.ctx.instantiate_typespec( self.ctx.instantiate_typespec(
@ -1339,7 +1338,7 @@ impl ASTLowerer {
) { ) {
(dunder_new_vi.t.clone(), new_vi.kind == VarKind::Auto) (dunder_new_vi.t.clone(), new_vi.kind == VarKind::Auto)
} else { } else {
return unreachable_error!(self); return unreachable_error!(LowerErrors, LowerError, self);
}; };
let require_or_sup = self.get_require_or_sup_or_base(hir_def.body.block.remove(0)); let require_or_sup = self.get_require_or_sup_or_base(hir_def.body.block.remove(0));
Ok(hir::ClassDef::new( Ok(hir::ClassDef::new(
@ -1591,12 +1590,12 @@ impl ASTLowerer {
} }
} }
other => { other => {
return todo_error!( return feature_error!(
self, LowerError,
self.ctx,
Location::Unknown, Location::Unknown,
&format!("Impl {other}") &format!("Impl {other}")
) );
.map_err(|mut e| e.remove(0));
} }
}, },
TypeObj::Builtin(_typ) => { TypeObj::Builtin(_typ) => {

View file

@ -8,8 +8,9 @@ use std::mem;
use std::ops::Neg; use std::ops::Neg;
use std::rc::Rc; use std::rc::Rc;
use erg_common::config::Input;
use erg_common::dict::Dict; use erg_common::dict::Dict;
use erg_common::error::ErrorCore; use erg_common::error::{ErrorCore, ErrorKind, Location};
use erg_common::fresh::fresh_varname; use erg_common::fresh::fresh_varname;
use erg_common::python_util::PythonVersion; use erg_common::python_util::PythonVersion;
use erg_common::serialize::*; use erg_common::serialize::*;
@ -44,6 +45,18 @@ impl From<EvalValueError> for ErrorCore {
} }
} }
impl EvalValueError {
pub fn feature_error(_input: Input, loc: Location, name: &str, caused_by: String) -> Self {
Self::from(ErrorCore::new(
vec![],
format!("{name} is not supported yet: {caused_by}"),
0,
ErrorKind::FeatureError,
loc,
))
}
}
pub type EvalValueResult<T> = Result<T, EvalValueError>; pub type EvalValueResult<T> = Result<T, EvalValueError>;
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]