fix: ignored match arms

This commit is contained in:
Shunsuke Shibayama 2024-08-29 02:37:19 +09:00
parent 8e9458e75a
commit 7e48a2f9c8
10 changed files with 633 additions and 138 deletions

View file

@ -18,7 +18,7 @@ use crate::ty::{HasType, Predicate, SubrType, Type};
use crate::context::{Context, Variance}; use crate::context::{Context, Variance};
use crate::error::{TyCheckError, TyCheckErrors, TyCheckResult}; use crate::error::{TyCheckError, TyCheckErrors, TyCheckResult};
use crate::{feature_error, hir, unreachable_error}; use crate::{feature_error, hir, mono_type_pattern, mono_value_pattern, unreachable_error};
use Type::*; use Type::*;
use Variance::*; use Variance::*;
@ -45,7 +45,10 @@ impl Generalizer {
fn generalize_tp(&mut self, free: TyParam, uninit: bool) -> TyParam { fn generalize_tp(&mut self, free: TyParam, uninit: bool) -> TyParam {
match free { match free {
TyParam::Type(t) => TyParam::t(self.generalize_t(*t, uninit)), TyParam::Type(t) => TyParam::t(self.generalize_t(*t, uninit)),
TyParam::Value(val) => TyParam::Value(val.map_t(&mut |t| self.generalize_t(t, uninit))), TyParam::Value(val) => TyParam::Value(
val.map_t(&mut |t| self.generalize_t(t, uninit))
.map_tp(&mut |tp| self.generalize_tp(tp, uninit)),
),
TyParam::FreeVar(fv) if fv.is_generalized() => TyParam::FreeVar(fv), TyParam::FreeVar(fv) if fv.is_generalized() => TyParam::FreeVar(fv),
TyParam::FreeVar(fv) if fv.is_linked() => { TyParam::FreeVar(fv) if fv.is_linked() => {
let tp = fv.crack().clone(); let tp = fv.crack().clone();
@ -63,6 +66,9 @@ impl Generalizer {
.map(|tp| self.generalize_tp(tp, uninit)) .map(|tp| self.generalize_tp(tp, uninit))
.collect(), .collect(),
), ),
TyParam::UnsizedList(tp) => {
TyParam::UnsizedList(Box::new(self.generalize_tp(*tp, uninit)))
}
TyParam::Tuple(tps) => TyParam::Tuple( TyParam::Tuple(tps) => TyParam::Tuple(
tps.into_iter() tps.into_iter()
.map(|tp| self.generalize_tp(tp, uninit)) .map(|tp| self.generalize_tp(tp, uninit))
@ -126,6 +132,14 @@ impl Generalizer {
let obj = self.generalize_tp(*obj, uninit); let obj = self.generalize_tp(*obj, uninit);
TyParam::proj(obj, attr) TyParam::proj(obj, attr)
} }
TyParam::ProjCall { obj, attr, args } => {
let obj = self.generalize_tp(*obj, uninit);
let args = args
.into_iter()
.map(|tp| self.generalize_tp(tp, uninit))
.collect();
TyParam::proj_call(obj, attr, args)
}
TyParam::Erased(t) => TyParam::erased(self.generalize_t(*t, uninit)), TyParam::Erased(t) => TyParam::erased(self.generalize_t(*t, uninit)),
TyParam::App { name, args } => { TyParam::App { name, args } => {
let args = args let args = args
@ -143,13 +157,7 @@ impl Generalizer {
let val = self.generalize_tp(*val, uninit); let val = self.generalize_tp(*val, uninit);
TyParam::unary(op, val) TyParam::unary(op, val)
} }
other if other.has_no_unbound_var() => other, TyParam::Mono(_) | TyParam::Failure => free,
other => {
if DEBUG_MODE {
todo!("{other:?}");
}
other
}
} }
} }
@ -201,6 +209,7 @@ impl Generalizer {
Type::FreeVar(fv) Type::FreeVar(fv)
} }
} }
FreeVar(_) => free_type,
Subr(mut subr) => { Subr(mut subr) => {
self.variance = Contravariant; self.variance = Contravariant;
let qnames = subr.essential_qnames(); let qnames = subr.essential_qnames();
@ -229,6 +238,10 @@ impl Generalizer {
return_t, return_t,
) )
} }
Quantified(quant) => {
log!(err "{quant}");
quant.quantify()
}
Record(rec) => { Record(rec) => {
let fields = rec let fields = rec
.into_iter() .into_iter()
@ -305,8 +318,14 @@ impl Generalizer {
let to = self.generalize_t(*grd.to, uninit); let to = self.generalize_t(*grd.to, uninit);
guard(grd.namespace, grd.target, to) guard(grd.namespace, grd.target, to)
} }
// REVIEW: その他何でもそのまま通していいのか? Bounded { sub, sup } => {
other => other, let sub = self.generalize_t(*sub, uninit);
let sup = self.generalize_t(*sup, uninit);
bounded(sub, sup)
}
Int | Nat | Float | Ratio | Complex | Bool | Str | Never | Obj | Type | Error
| Code | Frame | NoneType | Inf | NegInf | NotImplementedType | Ellipsis
| ClassType | TraitType | Patch | Failure | Uninited | Mono(_) => free_type,
} }
} }
@ -450,7 +469,7 @@ impl<'c, 'q, 'l, L: Locational> Dereferencer<'c, 'q, 'l, L> {
fn deref_value(&mut self, val: ValueObj) -> TyCheckResult<ValueObj> { fn deref_value(&mut self, val: ValueObj) -> TyCheckResult<ValueObj> {
match val { match val {
ValueObj::Type(mut t) => { ValueObj::Type(mut t) => {
t.try_map_t(|t| self.deref_tyvar(t.clone()))?; t.try_map_t(&mut |t| self.deref_tyvar(t.clone()))?;
Ok(ValueObj::Type(t)) Ok(ValueObj::Type(t))
} }
ValueObj::List(vs) => { ValueObj::List(vs) => {
@ -501,7 +520,8 @@ impl<'c, 'q, 'l, L: Locational> Dereferencer<'c, 'q, 'l, L> {
}) })
} }
ValueObj::UnsizedList(v) => Ok(ValueObj::UnsizedList(Box::new(self.deref_value(*v)?))), ValueObj::UnsizedList(v) => Ok(ValueObj::UnsizedList(Box::new(self.deref_value(*v)?))),
_ => Ok(val), ValueObj::Subr(subr) => Ok(ValueObj::Subr(subr)),
mono_value_pattern!() => Ok(val),
} }
} }
@ -526,6 +546,7 @@ impl<'c, 'q, 'l, L: Locational> Dereferencer<'c, 'q, 'l, L> {
fv.update_type(t); fv.update_type(t);
Ok(TyParam::FreeVar(fv)) Ok(TyParam::FreeVar(fv))
} }
TyParam::FreeVar(_) => Ok(tp),
TyParam::Type(t) => Ok(TyParam::t(self.deref_tyvar(*t)?)), TyParam::Type(t) => Ok(TyParam::t(self.deref_tyvar(*t)?)),
TyParam::Value(val) => self.deref_value(val).map(TyParam::Value), TyParam::Value(val) => self.deref_value(val).map(TyParam::Value),
TyParam::Erased(t) => Ok(TyParam::erased(self.deref_tyvar(*t)?)), TyParam::Erased(t) => Ok(TyParam::erased(self.deref_tyvar(*t)?)),
@ -558,6 +579,7 @@ impl<'c, 'q, 'l, L: Locational> Dereferencer<'c, 'q, 'l, L> {
} }
Ok(TyParam::List(new_tps)) Ok(TyParam::List(new_tps))
} }
TyParam::UnsizedList(tp) => Ok(TyParam::UnsizedList(Box::new(self.deref_tp(*tp)?))),
TyParam::Tuple(tps) => { TyParam::Tuple(tps) => {
let mut new_tps = vec![]; let mut new_tps = vec![];
for tp in tps { for tp in tps {
@ -609,20 +631,20 @@ impl<'c, 'q, 'l, L: Locational> Dereferencer<'c, 'q, 'l, L> {
let nd_params = lambda let nd_params = lambda
.nd_params .nd_params
.into_iter() .into_iter()
.map(|pt| pt.try_map_type(|t| self.deref_tyvar(t))) .map(|pt| pt.try_map_type(&mut |t| self.deref_tyvar(t)))
.collect::<TyCheckResult<_>>()?; .collect::<TyCheckResult<_>>()?;
let var_params = lambda let var_params = lambda
.var_params .var_params
.map(|pt| pt.try_map_type(|t| self.deref_tyvar(t))) .map(|pt| pt.try_map_type(&mut |t| self.deref_tyvar(t)))
.transpose()?; .transpose()?;
let d_params = lambda let d_params = lambda
.d_params .d_params
.into_iter() .into_iter()
.map(|pt| pt.try_map_type(|t| self.deref_tyvar(t))) .map(|pt| pt.try_map_type(&mut |t| self.deref_tyvar(t)))
.collect::<TyCheckResult<_>>()?; .collect::<TyCheckResult<_>>()?;
let kw_var_params = lambda let kw_var_params = lambda
.kw_var_params .kw_var_params
.map(|pt| pt.try_map_type(|t| self.deref_tyvar(t))) .map(|pt| pt.try_map_type(&mut |t| self.deref_tyvar(t)))
.transpose()?; .transpose()?;
let body = lambda let body = lambda
.body .body
@ -645,10 +667,22 @@ impl<'c, 'q, 'l, L: Locational> Dereferencer<'c, 'q, 'l, L> {
attr, attr,
}) })
} }
TyParam::ProjCall { obj, attr, args } => {
let obj = self.deref_tp(*obj)?;
let mut new_args = vec![];
for arg in args.into_iter() {
new_args.push(self.deref_tp(arg)?);
}
Ok(TyParam::ProjCall {
obj: Box::new(obj),
attr,
args: new_args,
})
}
TyParam::Failure if self.level == 0 => Err(TyCheckErrors::from( TyParam::Failure if self.level == 0 => Err(TyCheckErrors::from(
TyCheckError::dummy_infer_error(self.ctx.cfg.input.clone(), fn_name!(), line!()), TyCheckError::dummy_infer_error(self.ctx.cfg.input.clone(), fn_name!(), line!()),
)), )),
t => Ok(t), TyParam::Mono(_) | TyParam::Failure => Ok(tp),
} }
} }
@ -765,8 +799,12 @@ impl<'c, 'q, 'l, L: Locational> Dereferencer<'c, 'q, 'l, L> {
let pred = self.deref_pred(*pred)?; let pred = self.deref_pred(*pred)?;
Ok(!pred) Ok(!pred)
} }
Predicate::Attr { receiver, name } => {
let receiver = self.deref_tp(receiver)?;
Ok(Predicate::attr(receiver, name))
}
Predicate::Value(v) => self.deref_value(v).map(Predicate::Value), Predicate::Value(v) => self.deref_value(v).map(Predicate::Value),
_ => Ok(pred), Predicate::Const(_) | Predicate::Failure => Ok(pred),
} }
} }
@ -891,6 +929,7 @@ impl<'c, 'q, 'l, L: Locational> Dereferencer<'c, 'q, 'l, L> {
Ok(Type::FreeVar(fv)) Ok(Type::FreeVar(fv))
} }
} }
FreeVar(_) => Ok(t),
Poly { name, mut params } => { Poly { name, mut params } => {
let typ = poly(&name, params.clone()); let typ = poly(&name, params.clone());
let ctx = self.ctx.get_nominal_type_ctx(&typ).ok_or_else(|| { let ctx = self.ctx.get_nominal_type_ctx(&typ).ok_or_else(|| {
@ -1055,7 +1094,12 @@ impl<'c, 'q, 'l, L: Locational> Dereferencer<'c, 'q, 'l, L> {
let to = self.deref_tyvar(*grd.to)?; let to = self.deref_tyvar(*grd.to)?;
Ok(guard(grd.namespace, grd.target, to)) Ok(guard(grd.namespace, grd.target, to))
} }
t => Ok(t), Bounded { sub, sup } => {
let sub = self.deref_tyvar(*sub)?;
let sup = self.deref_tyvar(*sup)?;
Ok(bounded(sub, sup))
}
mono_type_pattern!() => Ok(t),
} }
} }

View file

@ -19,7 +19,7 @@ use crate::ty::ConstSubr;
use crate::ty::GuardType; use crate::ty::GuardType;
use crate::ty::ValueObj; use crate::ty::ValueObj;
use crate::ty::{HasType, Predicate, Type}; use crate::ty::{HasType, Predicate, Type};
use crate::{type_feature_error, unreachable_error}; use crate::{mono_type_pattern, unreachable_error};
use Type::*; use Type::*;
use crate::context::{Context, VarInfo}; use crate::context::{Context, VarInfo};
@ -40,7 +40,6 @@ pub struct TyVarCache {
pub(crate) tyvar_instances: Dict<VarName, Type>, pub(crate) tyvar_instances: Dict<VarName, Type>,
pub(crate) typaram_instances: Dict<VarName, TyParam>, pub(crate) typaram_instances: Dict<VarName, TyParam>,
pub(crate) var_infos: Dict<VarName, VarInfo>, pub(crate) var_infos: Dict<VarName, VarInfo>,
pub(crate) structural_inner: bool,
} }
impl fmt::Display for TyVarCache { impl fmt::Display for TyVarCache {
@ -61,7 +60,6 @@ impl TyVarCache {
tyvar_instances: Dict::new(), tyvar_instances: Dict::new(),
typaram_instances: Dict::new(), typaram_instances: Dict::new(),
var_infos: Dict::new(), var_infos: Dict::new(),
structural_inner: false,
} }
} }
@ -419,6 +417,8 @@ impl Context {
tmp_tv_cache.instantiate_constraint(constr, self, loc)?; tmp_tv_cache.instantiate_constraint(constr, self, loc)?;
fv.update_constraint(new_constr, true); fv.update_constraint(new_constr, true);
} }
} else {
todo!("{tp}");
} }
Ok(tp) Ok(tp)
} else if let Some(t) = tmp_tv_cache.get_tyvar(&name) { } else if let Some(t) = tmp_tv_cache.get_tyvar(&name) {
@ -433,6 +433,8 @@ impl Context {
tmp_tv_cache.instantiate_constraint(constr, self, loc)?; tmp_tv_cache.instantiate_constraint(constr, self, loc)?;
fv.update_constraint(new_constr, true); fv.update_constraint(new_constr, true);
} }
} else {
todo!("{t}");
} }
Ok(TyParam::t(t)) Ok(TyParam::t(t))
} else { } else {
@ -517,20 +519,28 @@ impl Context {
let nd_params = lambda let nd_params = lambda
.nd_params .nd_params
.into_iter() .into_iter()
.map(|pt| pt.try_map_type(|t| self.instantiate_t_inner(t, tmp_tv_cache, loc))) .map(|pt| {
pt.try_map_type(&mut |t| self.instantiate_t_inner(t, tmp_tv_cache, loc))
})
.collect::<TyCheckResult<_>>()?; .collect::<TyCheckResult<_>>()?;
let var_params = lambda let var_params = lambda
.var_params .var_params
.map(|pt| pt.try_map_type(|t| self.instantiate_t_inner(t, tmp_tv_cache, loc))) .map(|pt| {
pt.try_map_type(&mut |t| self.instantiate_t_inner(t, tmp_tv_cache, loc))
})
.transpose()?; .transpose()?;
let d_params = lambda let d_params = lambda
.d_params .d_params
.into_iter() .into_iter()
.map(|pt| pt.try_map_type(|t| self.instantiate_t_inner(t, tmp_tv_cache, loc))) .map(|pt| {
pt.try_map_type(&mut |t| self.instantiate_t_inner(t, tmp_tv_cache, loc))
})
.collect::<TyCheckResult<_>>()?; .collect::<TyCheckResult<_>>()?;
let kw_var_params = lambda let kw_var_params = lambda
.kw_var_params .kw_var_params
.map(|pt| pt.try_map_type(|t| self.instantiate_t_inner(t, tmp_tv_cache, loc))) .map(|pt| {
pt.try_map_type(&mut |t| self.instantiate_t_inner(t, tmp_tv_cache, loc))
})
.transpose()?; .transpose()?;
let body = lambda let body = lambda
.body .body
@ -579,21 +589,17 @@ impl Context {
Ok(TyParam::t(t)) Ok(TyParam::t(t))
} }
TyParam::Value(val) => { TyParam::Value(val) => {
// println!("592: {val} / {tmp_tv_cache}");
let val = val.try_map_t(&mut |t| self.instantiate_t_inner(t, tmp_tv_cache, loc))?; let val = val.try_map_t(&mut |t| self.instantiate_t_inner(t, tmp_tv_cache, loc))?;
// .try_map_tp(&mut |tp| self.instantiate_tp(tp, tmp_tv_cache, loc))?;
// println!("596: {val} / {tmp_tv_cache}");
Ok(TyParam::Value(val)) Ok(TyParam::Value(val))
} }
TyParam::Erased(t) => { TyParam::Erased(t) => {
let t = self.instantiate_t_inner(*t, tmp_tv_cache, loc)?; let t = self.instantiate_t_inner(*t, tmp_tv_cache, loc)?;
Ok(TyParam::Erased(Box::new(t))) Ok(TyParam::Erased(Box::new(t)))
} }
p @ (TyParam::Mono(_) | TyParam::FreeVar(_)) => Ok(p), p @ (TyParam::Mono(_) | TyParam::FreeVar(_) | TyParam::Failure) => Ok(p),
other => {
type_feature_error!(
self,
loc.loc(),
&format!("instantiating type-parameter {other}")
)
}
} }
} }
@ -670,7 +676,11 @@ impl Context {
let rhs = self.instantiate_pred(*rhs, tmp_tv_cache, loc)?; let rhs = self.instantiate_pred(*rhs, tmp_tv_cache, loc)?;
Ok(Predicate::general_ne(lhs, rhs)) Ok(Predicate::general_ne(lhs, rhs))
} }
_ => Ok(pred), Predicate::Attr { receiver, name } => {
let receiver = self.instantiate_tp(receiver, tmp_tv_cache, loc)?;
Ok(Predicate::attr(receiver, name))
}
Predicate::Const(_) | Predicate::Failure => Ok(pred),
} }
} }
@ -714,6 +724,10 @@ impl Context {
} }
Ok(ValueObj::List(new.into())) Ok(ValueObj::List(new.into()))
} }
ValueObj::UnsizedList(lis) => {
let lis = self.instantiate_value(*lis, tmp_tv_cache, loc)?;
Ok(ValueObj::UnsizedList(Box::new(lis)))
}
ValueObj::Tuple(tup) => { ValueObj::Tuple(tup) => {
let mut new = vec![]; let mut new = vec![];
for v in tup.iter().cloned() { for v in tup.iter().cloned() {
@ -754,7 +768,18 @@ impl Context {
} }
Ok(ValueObj::DataClass { name, fields: new }) Ok(ValueObj::DataClass { name, fields: new })
} }
_ => Ok(value), ValueObj::Int(_)
| ValueObj::Nat(_)
| ValueObj::Float(_)
| ValueObj::Str(_)
| ValueObj::Bool(_)
| ValueObj::Code(_)
| ValueObj::None
| ValueObj::Ellipsis
| ValueObj::Inf
| ValueObj::NegInf
| ValueObj::NotImplemented
| ValueObj::Failure => Ok(value),
} }
} }
@ -776,8 +801,7 @@ impl Context {
let t = t.clone(); let t = t.clone();
Ok(t) Ok(t)
} else if let Some(tp) = tmp_tv_cache.get_typaram(&name) { } else if let Some(tp) = tmp_tv_cache.get_typaram(&name) {
if let TyParam::Type(t) = tp { if let Ok(t) = self.convert_tp_into_type(tp.clone()) {
let t = *t.clone();
Ok(t) Ok(t)
} else { } else {
todo!( todo!(
@ -797,8 +821,8 @@ impl Context {
if let Some(t) = tv_ctx.get_tyvar(&name) { if let Some(t) = tv_ctx.get_tyvar(&name) {
return Ok(t.clone()); return Ok(t.clone());
} else if let Some(tp) = tv_ctx.get_typaram(&name) { } else if let Some(tp) = tv_ctx.get_typaram(&name) {
if let TyParam::Type(t) = tp { if let Ok(t) = self.convert_tp_into_type(tp.clone()) {
return Ok(*t.clone()); return Ok(t);
} else { } else {
todo!( todo!(
"typaram_insts: {}\ntyvar_insts:{}\n{tp}", "typaram_insts: {}\ntyvar_insts:{}\n{tp}",
@ -902,16 +926,8 @@ impl Context {
Ok(poly(name, params)) Ok(poly(name, params))
} }
Structural(t) => { Structural(t) => {
// avoid infinite recursion let t = self.instantiate_t_inner(*t, tmp_tv_cache, loc)?;
if tmp_tv_cache.structural_inner { Ok(t.structuralize())
Ok(t.structuralize())
} else {
if t.is_recursive() {
tmp_tv_cache.structural_inner = true;
}
let t = self.instantiate_t_inner(*t, tmp_tv_cache, loc)?;
Ok(t.structuralize())
}
} }
FreeVar(fv) => { FreeVar(fv) => {
if let Some((sub, sup)) = fv.get_subsup() { if let Some((sub, sup)) = fv.get_subsup() {
@ -961,8 +977,15 @@ impl Context {
let sup = self.instantiate_t_inner(*sup, tmp_tv_cache, loc)?; let sup = self.instantiate_t_inner(*sup, tmp_tv_cache, loc)?;
Ok(bounded(sub, sup)) Ok(bounded(sub, sup))
} }
other if other.is_monomorphic() => Ok(other), Callable { param_ts, return_t } => {
other => type_feature_error!(self, loc.loc(), &format!("instantiating type {other}")), let param_ts = param_ts
.into_iter()
.map(|t| self.instantiate_t_inner(t, tmp_tv_cache, loc))
.collect::<TyCheckResult<_>>()?;
let return_t = self.instantiate_t_inner(*return_t, tmp_tv_cache, loc)?;
Ok(callable(param_ts, return_t))
}
mono_type_pattern!() => Ok(unbound),
} }
} }
@ -983,9 +1006,9 @@ impl Context {
if let Some(self_t) = ty.self_t() { if let Some(self_t) = ty.self_t() {
self.sub_unify(callee.ref_t(), self_t, callee, Some(&Str::ever("self")))?; self.sub_unify(callee.ref_t(), self_t, callee, Some(&Str::ever("self")))?;
} }
if cfg!(feature = "debug") && ty.has_qvar() { /*if DEBUG_MODE && ty.has_qvar() {
panic!("{ty} has qvar") panic!("{ty} has qvar")
} }*/
Ok(ty) Ok(ty)
} }
// HACK: {op: |T|(T -> T) | op == F} => ?T -> ?T // HACK: {op: |T|(T -> T) | op == F} => ?T -> ?T
@ -1028,6 +1051,7 @@ impl Context {
log!(err "{subr} has qvar"); log!(err "{subr} has qvar");
self.instantiate(Type::Subr(subr).quantify(), callee) self.instantiate(Type::Subr(subr).quantify(), callee)
} }
// There are no quantified types inside normal types (rank-0 types) due to the rank-1 restriction
// rank-1制限により、通常の型(rank-0型)の内側に量化型は存在しない // rank-1制限により、通常の型(rank-0型)の内側に量化型は存在しない
other => Ok(other), other => Ok(other),
} }
@ -1047,9 +1071,9 @@ impl Context {
Quantified(quant) => { Quantified(quant) => {
let mut tmp_tv_cache = TyVarCache::new(self.level, self); let mut tmp_tv_cache = TyVarCache::new(self.level, self);
let ty = self.instantiate_t_inner(*quant, &mut tmp_tv_cache, &())?; let ty = self.instantiate_t_inner(*quant, &mut tmp_tv_cache, &())?;
if cfg!(feature = "debug") && ty.has_qvar() { /*if DEBUG_MODE && ty.has_qvar() {
panic!("{ty} has qvar") panic!("{ty} has qvar")
} }*/
Ok(ty) Ok(ty)
} }
Refinement(refine) if refine.t.is_quantified_subr() => { Refinement(refine) if refine.t.is_quantified_subr() => {

View file

@ -1293,21 +1293,25 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> {
} }
} }
} }
(FreeVar(sub_fv), Structural(sup)) if sub_fv.is_unbound() => { (FreeVar(sub_fv), Structural(struct_sup)) if sub_fv.is_unbound() => {
if sub_fv.get_sub().is_none() { let Some((sub, sup)) = sub_fv.get_subsup() else {
log!(err "{sub_fv} is not a type variable"); log!(err "{sub_fv} is not a type variable");
return Ok(()); return Ok(());
} };
let sub_fields = self.ctx.fields(maybe_sub); let sub_fields = self.ctx.fields(maybe_sub);
for (sup_field, sup_ty) in self.ctx.fields(sup) { for (sup_field, sup_ty) in self.ctx.fields(struct_sup) {
if let Some((_, sub_ty)) = sub_fields.get_key_value(&sup_field) { if let Some((_, sub_ty)) = sub_fields.get_key_value(&sup_field) {
self.sub_unify(sub_ty, &sup_ty)?; self.sub_unify(sub_ty, &sup_ty)?;
} else if !self.ctx.subtype_of(&sub_fv.get_sub().unwrap(), &Never) { } else if !self.ctx.subtype_of(&sub, &Never) {
maybe_sub.coerce(self.undoable); maybe_sub.coerce(self.undoable);
return self.sub_unify(maybe_sub, maybe_sup); return self.sub_unify(maybe_sub, maybe_sup);
} else { } else {
// e.g. ?T / Structural({ .method = (self: ?T) -> Int }) // e.g. ?T / Structural({ .method = (self: ?T) -> Int })
sub_fv.update_super(|sup| self.ctx.intersection(&sup, maybe_sup)); let constr = Constraint::new_sandwiched(
sub.clone(),
self.ctx.intersection(&sup, maybe_sup),
);
sub_fv.update_constraint(constr, false);
} }
} }
} }

View file

@ -59,7 +59,7 @@ impl SharedCompilerResource {
pub fn inherit<P: Into<NormalizedPathBuf>>(&self, path: P) -> Self { pub fn inherit<P: Into<NormalizedPathBuf>>(&self, path: P) -> Self {
let mut _self = self.clone(); let mut _self = self.clone();
_self.promises.path = path.into(); _self.promises.root = path.into();
_self _self
} }

View file

@ -83,7 +83,7 @@ pub struct Progress {
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct SharedPromises { pub struct SharedPromises {
graph: SharedModuleGraph, graph: SharedModuleGraph,
pub(crate) path: NormalizedPathBuf, pub(crate) root: NormalizedPathBuf,
promises: Shared<Dict<NormalizedPathBuf, Promise>>, promises: Shared<Dict<NormalizedPathBuf, Promise>>,
} }
@ -98,10 +98,10 @@ impl fmt::Display for SharedPromises {
} }
impl SharedPromises { impl SharedPromises {
pub fn new(graph: SharedModuleGraph, path: NormalizedPathBuf) -> Self { pub fn new(graph: SharedModuleGraph, root: NormalizedPathBuf) -> Self {
Self { Self {
graph, graph,
path, root,
promises: Shared::new(Dict::new()), promises: Shared::new(Dict::new()),
} }
} }
@ -153,25 +153,28 @@ impl SharedPromises {
} }
pub fn wait_until_finished(&self, path: &NormalizedPathBuf) { pub fn wait_until_finished(&self, path: &NormalizedPathBuf) {
if self.promises.borrow().get(path).is_none() {
panic!("not registered: {path}");
}
while !self.is_finished(path) { while !self.is_finished(path) {
safe_yield(); safe_yield();
} }
} }
pub fn join(&self, path: &NormalizedPathBuf) -> std::thread::Result<()> { pub fn join(&self, path: &NormalizedPathBuf) -> std::thread::Result<()> {
if self.graph.ancestors(path).contains(&self.path) { if self.graph.ancestors(path).contains(&self.root) {
// cycle detected, `self.path` must not in the dependencies // cycle detected, `self.path` must not in the dependencies
// Erg analysis processes never join ancestor threads (although joining ancestors itself is allowed in Rust) // Erg analysis processes never join ancestor threads (although joining ancestors itself is allowed in Rust)
self.wait_until_finished(path); // self.wait_until_finished(path);
return Ok(()); return Ok(());
} }
// Suppose A depends on B and C, and B depends on C. // Suppose A depends on B and C, and B depends on C.
// In this case, B must join C before A joins C. Otherwise, a deadlock will occur. // In this case, B must join C before A joins C. Otherwise, a deadlock will occur.
let children = self.graph.children(path); let children = self.graph.children(path);
for child in children.iter() { for child in children.iter() {
if child == &self.path { if child == &self.root {
continue; continue;
} else if self.graph.depends_on(&self.path, child) { } else if self.graph.depends_on(&self.root, child) {
self.wait_until_finished(path); self.wait_until_finished(path);
return Ok(()); return Ok(());
} }

View file

@ -35,6 +35,9 @@ pub trait HasLevel {
} }
fn lower(&self) { fn lower(&self) {
if let Some(lev) = self.level() { if let Some(lev) = self.level() {
if lev == GENERIC_LEVEL {
return;
}
self.set_level(lev.saturating_sub(1)); self.set_level(lev.saturating_sub(1));
} }
} }
@ -808,6 +811,10 @@ impl HasLevel for Free<Type> {
if addr_eq!(*lev, level) { if addr_eq!(*lev, level) {
return; return;
} }
// GENERIC_LEVEL variable cannot be lowered
if *lev == GENERIC_LEVEL && level == GENERIC_LEVEL - 1 {
return;
}
*lev = level; *lev = level;
} }
_ => {} _ => {}
@ -1143,7 +1150,7 @@ impl<T: CanbeFree + Send + Clone> Free<T> {
/// if `in_inst_or_gen` is true, constraint will be updated forcibly /// if `in_inst_or_gen` is true, constraint will be updated forcibly
pub fn update_constraint(&self, new_constraint: Constraint, in_inst_or_gen: bool) { pub fn update_constraint(&self, new_constraint: Constraint, in_inst_or_gen: bool) {
if new_constraint.get_type() == Some(&Type::Never) { if new_constraint.get_type() == Some(&Type::Never) {
panic!(); panic!("{new_constraint}");
} }
match &mut *self.borrow_mut() { match &mut *self.borrow_mut() {
FreeKind::Unbound { FreeKind::Unbound {
@ -1168,20 +1175,14 @@ impl<T: CanbeFree + Send + Clone> Free<T> {
} }
/// interior-mut /// interior-mut
pub fn update_sub<F>(&self, f: F) pub fn update_sub(&self, f: impl FnOnce(Type) -> Type) {
where
F: FnOnce(Type) -> Type,
{
let (sub, sup) = self.get_subsup().unwrap(); let (sub, sup) = self.get_subsup().unwrap();
let new_constraint = Constraint::new_sandwiched(f(sub), sup); let new_constraint = Constraint::new_sandwiched(f(sub), sup);
self.update_constraint(new_constraint, true); self.update_constraint(new_constraint, true);
} }
/// interior-mut /// interior-mut
pub fn update_super<F>(&self, f: F) pub fn update_super(&self, f: impl FnOnce(Type) -> Type) {
where
F: FnOnce(Type) -> Type,
{
let (sub, sup) = self.get_subsup().unwrap(); let (sub, sup) = self.get_subsup().unwrap();
let new_constraint = Constraint::new_sandwiched(sub, f(sup)); let new_constraint = Constraint::new_sandwiched(sub, f(sup));
self.update_constraint(new_constraint, true); self.update_constraint(new_constraint, true);
@ -1195,10 +1196,7 @@ impl<T: CanbeFree + Send + Clone> Free<T> {
} }
impl Free<TyParam> { impl Free<TyParam> {
pub fn map<F>(&self, f: F) pub fn map(&self, f: impl Fn(TyParam) -> TyParam) {
where
F: Fn(TyParam) -> TyParam,
{
if let Some(mut linked) = self.get_linked_refmut() { if let Some(mut linked) = self.get_linked_refmut() {
let mapped = f(mem::take(&mut *linked)); let mapped = f(mem::take(&mut *linked));
*linked = mapped; *linked = mapped;

View file

@ -54,6 +54,36 @@ pub const STR_OMIT_THRESHOLD: usize = if DEBUG_MODE { 100 } else { 16 };
pub const CONTAINER_OMIT_THRESHOLD: usize = if DEBUG_MODE { 100 } else { 8 }; pub const CONTAINER_OMIT_THRESHOLD: usize = if DEBUG_MODE { 100 } else { 8 };
pub const DEFAULT_PARAMS_THRESHOLD: usize = if DEBUG_MODE { 100 } else { 5 }; pub const DEFAULT_PARAMS_THRESHOLD: usize = if DEBUG_MODE { 100 } else { 5 };
#[macro_export]
macro_rules! mono_type_pattern {
() => {
$crate::ty::Type::Int
| $crate::ty::Type::Nat
| $crate::ty::Type::Float
| $crate::ty::Type::Ratio
| $crate::ty::Type::Complex
| $crate::ty::Type::Inf
| $crate::ty::Type::NegInf
| $crate::ty::Type::Bool
| $crate::ty::Type::Str
| $crate::ty::Type::Code
| $crate::ty::Type::Frame
| $crate::ty::Type::Type
| $crate::ty::Type::TraitType
| $crate::ty::Type::ClassType
| $crate::ty::Type::Patch
| $crate::ty::Type::NoneType
| $crate::ty::Type::NotImplementedType
| $crate::ty::Type::Ellipsis
| $crate::ty::Type::Error
| $crate::ty::Type::Obj
| $crate::ty::Type::Never
| $crate::ty::Type::Failure
| $crate::ty::Type::Mono(_)
| $crate::ty::Type::Uninited
};
}
/// cloneのコストがあるためなるべく.ref_tを使うようにすること /// cloneのコストがあるためなるべく.ref_tを使うようにすること
/// いくつかの構造体は直接Typeを保持していないので、その場合は.tを使う /// いくつかの構造体は直接Typeを保持していないので、その場合は.tを使う
#[allow(unused_variables)] #[allow(unused_variables)]
@ -256,10 +286,7 @@ impl ParamTy {
} }
} }
pub fn try_map_type<F, E>(self, f: F) -> Result<Self, E> pub fn try_map_type<E>(self, f: &mut impl FnMut(Type) -> Result<Type, E>) -> Result<Self, E> {
where
F: FnOnce(Type) -> Result<Type, E>,
{
match self { match self {
Self::Pos(ty) => Ok(Self::Pos(f(ty)?)), Self::Pos(ty) => Ok(Self::Pos(f(ty)?)),
Self::Kw { name, ty } => Ok(Self::Kw { name, ty: f(ty)? }), Self::Kw { name, ty } => Ok(Self::Kw { name, ty: f(ty)? }),
@ -271,6 +298,20 @@ impl ParamTy {
} }
} }
pub fn try_map_default_type<E>(
self,
f: &mut impl FnMut(Type) -> Result<Type, E>,
) -> Result<Self, E> {
match self {
Self::KwWithDefault { name, ty, default } => Ok(Self::KwWithDefault {
name,
ty,
default: f(default)?,
}),
_ => Ok(self),
}
}
pub fn deconstruct(self) -> (Option<Str>, Type, Option<Type>) { pub fn deconstruct(self) -> (Option<Str>, Type, Option<Type>) {
match self { match self {
Self::Pos(ty) => (None, ty, None), Self::Pos(ty) => (None, ty, None),
@ -532,24 +573,55 @@ impl SubrType {
) )
} }
pub fn map_tp(self, f: impl Fn(TyParam) -> TyParam + Copy) -> Self { pub fn map_tp(self, f: &mut impl FnMut(TyParam) -> TyParam) -> Self {
let f = |t: Type| t.map_tp(f); let mut f_ = |t: Type| t.map_tp(f);
Self::new( Self::new(
self.kind, self.kind,
self.non_default_params self.non_default_params
.into_iter() .into_iter()
.map(|pt| pt.map_type(f)) .map(|pt| pt.map_type(&mut f_))
.collect(), .collect(),
self.var_params.map(|pt| pt.map_type(f)), self.var_params.map(|pt| pt.map_type(&mut f_)),
self.default_params self.default_params
.into_iter() .into_iter()
.map(|pt| pt.map_type(f).map_default_type(f)) .map(|pt| pt.map_type(&mut f_).map_default_type(&mut f_))
.collect(), .collect(),
self.kw_var_params.map(|pt| pt.map_type(f)), self.kw_var_params.map(|pt| pt.map_type(&mut f_)),
f(*self.return_t), f_(*self.return_t),
) )
} }
pub fn try_map_tp<E>(
self,
f: &mut impl FnMut(TyParam) -> Result<TyParam, E>,
) -> Result<Self, E> {
let mut f_ = |t: Type| t.try_map_tp(f);
let var_params = if let Some(var_params) = self.var_params {
Some(var_params.try_map_type(&mut f_)?)
} else {
None
};
let kw_var_params = if let Some(kw_var_params) = self.kw_var_params {
Some(kw_var_params.try_map_type(&mut f_)?)
} else {
None
};
Ok(Self::new(
self.kind,
self.non_default_params
.into_iter()
.map(|pt| pt.try_map_type(&mut f_))
.collect::<Result<_, _>>()?,
var_params,
self.default_params
.into_iter()
.map(|pt| pt.try_map_type(&mut f_)?.try_map_default_type(&mut f_))
.collect::<Result<_, _>>()?,
kw_var_params,
self.return_t.try_map_tp(f)?,
))
}
pub fn contains_value(&self, target: &ValueObj) -> bool { pub fn contains_value(&self, target: &ValueObj) -> bool {
self.non_default_params self.non_default_params
.iter() .iter()
@ -3334,8 +3406,12 @@ impl Type {
} }
Type::FreeVar(fv) if fv.is_unbound_and_sandwiched() => { Type::FreeVar(fv) if fv.is_unbound_and_sandwiched() => {
let (sub, _sup) = fv.get_subsup().unwrap(); let (sub, _sup) = fv.get_subsup().unwrap();
sub.destructive_coerce(); if self.addr_eq(&sub) {
self.destructive_link(&sub); self.destructive_link(&Type::Never);
} else {
sub.destructive_coerce();
self.destructive_link(&sub);
}
} }
Type::And(l, r) | Type::Or(l, r) => { Type::And(l, r) | Type::Or(l, r) => {
l.destructive_coerce(); l.destructive_coerce();
@ -3349,6 +3425,32 @@ impl Type {
} }
} }
} }
Type::Bounded { sub, sup } => {
sub.destructive_coerce();
sup.destructive_coerce();
}
Type::Ref(t) => t.destructive_coerce(),
Type::RefMut { before, after } => {
before.destructive_coerce();
if let Some(after) = after {
after.destructive_coerce();
}
}
Type::Structural(ty) => ty.destructive_coerce(),
Type::Record(r) => {
for t in r.values() {
t.destructive_coerce();
}
}
Type::NamedTuple(r) => {
for (_, t) in r.iter() {
t.destructive_coerce();
}
}
Type::Refinement(refine) => {
refine.t.destructive_coerce();
// refine.pred.destructive_coerce();
}
Type::Subr(subr) => subr.destructive_coerce(), Type::Subr(subr) => subr.destructive_coerce(),
// TODO: // TODO:
_ => {} _ => {}
@ -3362,8 +3464,12 @@ impl Type {
} }
Type::FreeVar(fv) if fv.is_unbound_and_sandwiched() => { Type::FreeVar(fv) if fv.is_unbound_and_sandwiched() => {
let (sub, _sup) = fv.get_subsup().unwrap(); let (sub, _sup) = fv.get_subsup().unwrap();
sub.undoable_coerce(list); if self.addr_eq(&sub) {
self.undoable_link(&sub, list); self.undoable_link(&Type::Never, list);
} else {
sub.undoable_coerce(list);
self.undoable_link(&sub, list);
}
} }
Type::And(l, r) | Type::Or(l, r) => { Type::And(l, r) | Type::Or(l, r) => {
l.undoable_coerce(list); l.undoable_coerce(list);
@ -3831,7 +3937,7 @@ impl Type {
// At least in situations where this function is needed, self cannot be Quantified. // At least in situations where this function is needed, self cannot be Quantified.
Self::Quantified(quant) => { Self::Quantified(quant) => {
if quant.return_t()?.is_generalized() { if quant.return_t()?.is_generalized() {
log!(err "quantified return type (recursive function type inference)"); log!(err "quantified return type (recursive function type inference?)");
} }
quant.return_t() quant.return_t()
} }
@ -4334,7 +4440,7 @@ impl Type {
} }
} }
fn map_tp(self, f: impl Fn(TyParam) -> TyParam + Copy) -> Type { fn map_tp(self, f: &mut impl FnMut(TyParam) -> TyParam) -> Type {
match self { match self {
Self::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().map_tp(f), Self::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().map_tp(f),
Self::FreeVar(fv) => { Self::FreeVar(fv) => {
@ -4411,6 +4517,96 @@ impl Type {
} }
} }
pub fn try_map_tp<E>(
self,
f: &mut impl FnMut(TyParam) -> Result<TyParam, E>,
) -> Result<Type, E> {
match self {
Self::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().try_map_tp(f),
Self::FreeVar(fv) => {
let fv_clone = fv.deep_clone();
if let Some((sub, sup)) = fv_clone.get_subsup() {
fv.dummy_link();
fv_clone.dummy_link();
let sub = sub.try_map_tp(f)?;
let sup = sup.try_map_tp(f)?;
fv.undo();
fv_clone.undo();
fv_clone.update_constraint(Constraint::new_sandwiched(sub, sup), true);
} else if let Some(ty) = fv_clone.get_type() {
fv_clone.update_constraint(Constraint::new_type_of(ty.try_map_tp(f)?), true);
}
Ok(Self::FreeVar(fv_clone))
}
Self::Refinement(mut refine) => {
refine.t = Box::new(refine.t.try_map_tp(f)?);
refine.pred = Box::new(refine.pred.try_map_tp(f)?);
Ok(Self::Refinement(refine))
}
Self::Record(mut rec) => {
for v in rec.values_mut() {
*v = std::mem::take(v).try_map_tp(f)?;
}
Ok(Self::Record(rec))
}
Self::NamedTuple(mut r) => {
for (_, v) in r.iter_mut() {
*v = std::mem::take(v).try_map_tp(f)?;
}
Ok(Self::NamedTuple(r))
}
Self::Subr(subr) => Ok(Self::Subr(subr.try_map_tp(f)?)),
Self::Callable { param_ts, return_t } => {
let param_ts = param_ts
.into_iter()
.map(|t| t.try_map_tp(f))
.collect::<Result<_, _>>()?;
let return_t = Box::new(return_t.try_map_tp(f)?);
Ok(Self::Callable { param_ts, return_t })
}
Self::Quantified(quant) => Ok(quant.try_map_tp(f)?.quantify()),
Self::Poly { name, params } => {
let params = params.into_iter().map(f).collect::<Result<_, _>>()?;
Ok(Self::Poly { name, params })
}
Self::Ref(t) => Ok(Self::Ref(Box::new(t.try_map_tp(f)?))),
Self::RefMut { before, after } => {
let after = match after {
Some(t) => Some(Box::new(t.try_map_tp(f)?)),
None => None,
};
Ok(Self::RefMut {
before: Box::new(before.try_map_tp(f)?),
after,
})
}
Self::And(l, r) => Ok(l.try_map_tp(f)? & r.try_map_tp(f)?),
Self::Or(l, r) => Ok(l.try_map_tp(f)? | r.try_map_tp(f)?),
Self::Not(ty) => Ok(!ty.try_map_tp(f)?),
Self::Proj { lhs, rhs } => Ok(lhs.try_map_tp(f)?.proj(rhs)),
Self::ProjCall {
lhs,
attr_name,
args,
} => {
let lhs = f(*lhs)?;
let args = args.into_iter().map(f).collect::<Result<_, _>>()?;
Ok(proj_call(lhs, attr_name, args))
}
Self::Structural(ty) => Ok(ty.try_map_tp(f)?.structuralize()),
Self::Guard(guard) => Ok(Self::Guard(GuardType::new(
guard.namespace,
guard.target.clone(),
guard.to.try_map_tp(f)?,
))),
Self::Bounded { sub, sup } => Ok(Self::Bounded {
sub: Box::new(sub.try_map_tp(f)?),
sup: Box::new(sup.try_map_tp(f)?),
}),
mono_type_pattern!() => Ok(self),
}
}
fn replace_param(self, target: &str, to: &str) -> Self { fn replace_param(self, target: &str, to: &str) -> Self {
match self { match self {
Self::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().replace_param(target, to), Self::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().replace_param(target, to),
@ -4540,9 +4736,9 @@ impl Type {
return; return;
} }
if self.level() == Some(GENERIC_LEVEL) { if self.level() == Some(GENERIC_LEVEL) {
if DEBUG_MODE { /*if DEBUG_MODE {
panic!("{self} is fixed"); panic!("{self} is fixed");
} }*/
return; return;
} }
let to = to.clone().eliminate_sub(self).eliminate_recursion(self); let to = to.clone().eliminate_sub(self).eliminate_recursion(self);

View file

@ -929,11 +929,11 @@ impl Predicate {
} }
pub fn _replace_tp(self, target: &TyParam, to: &TyParam) -> Self { pub fn _replace_tp(self, target: &TyParam, to: &TyParam) -> Self {
self.map_tp(|tp| tp._replace(target, to)) self.map_tp(&mut |tp| tp._replace(target, to))
} }
pub fn replace_tp(self, target: &TyParam, to: &TyParam) -> Self { pub fn replace_tp(self, target: &TyParam, to: &TyParam) -> Self {
self.map_tp(|tp| tp.replace(target, to)) self.map_tp(&mut |tp| tp.replace(target, to))
} }
pub fn _replace_t(self, target: &Type, to: &Type) -> Self { pub fn _replace_t(self, target: &Type, to: &Type) -> Self {
@ -1003,7 +1003,7 @@ impl Predicate {
} }
} }
pub fn map_tp(self, f: impl Fn(TyParam) -> TyParam + Copy) -> Self { pub fn map_tp(self, f: &mut impl FnMut(TyParam) -> TyParam) -> Self {
match self { match self {
Self::Value(val) => Self::Value(val.map_tp(f)), Self::Value(val) => Self::Value(val.map_tp(f)),
Self::Const(_) => self, Self::Const(_) => self,
@ -1058,4 +1058,56 @@ impl Predicate {
_ => self, _ => self,
} }
} }
pub fn try_map_tp<E>(
self,
f: &mut impl FnMut(TyParam) -> Result<TyParam, E>,
) -> Result<Self, E> {
match self {
Self::Value(val) => Ok(Self::Value(val.try_map_tp(f)?)),
Self::Call {
receiver,
args,
name,
} => Ok(Self::Call {
receiver: f(receiver)?,
args: args.into_iter().map(f).collect::<Result<_, E>>()?,
name,
}),
Self::Attr { receiver, name } => Ok(Self::Attr {
receiver: f(receiver)?,
name,
}),
Self::Equal { lhs, rhs } => Ok(Self::Equal { lhs, rhs: f(rhs)? }),
Self::GreaterEqual { lhs, rhs } => Ok(Self::GreaterEqual { lhs, rhs: f(rhs)? }),
Self::LessEqual { lhs, rhs } => Ok(Self::LessEqual { lhs, rhs: f(rhs)? }),
Self::NotEqual { lhs, rhs } => Ok(Self::NotEqual { lhs, rhs: f(rhs)? }),
Self::GeneralEqual { lhs, rhs } => Ok(Self::GeneralEqual {
lhs: Box::new(lhs.try_map_tp(f)?),
rhs: Box::new(rhs.try_map_tp(f)?),
}),
Self::GeneralLessEqual { lhs, rhs } => Ok(Self::GeneralLessEqual {
lhs: Box::new(lhs.try_map_tp(f)?),
rhs: Box::new(rhs.try_map_tp(f)?),
}),
Self::GeneralGreaterEqual { lhs, rhs } => Ok(Self::GeneralGreaterEqual {
lhs: Box::new(lhs.try_map_tp(f)?),
rhs: Box::new(rhs.try_map_tp(f)?),
}),
Self::GeneralNotEqual { lhs, rhs } => Ok(Self::GeneralNotEqual {
lhs: Box::new(lhs.try_map_tp(f)?),
rhs: Box::new(rhs.try_map_tp(f)?),
}),
Self::And(lhs, rhs) => Ok(Self::And(
Box::new(lhs.try_map_tp(f)?),
Box::new(rhs.try_map_tp(f)?),
)),
Self::Or(lhs, rhs) => Ok(Self::Or(
Box::new(lhs.try_map_tp(f)?),
Box::new(rhs.try_map_tp(f)?),
)),
Self::Not(pred) => Ok(Self::Not(Box::new(pred.try_map_tp(f)?))),
_ => Ok(self),
}
}
} }

View file

@ -1531,7 +1531,7 @@ impl TyParam {
if self.qual_name().is_some_and(|n| n == var) { if self.qual_name().is_some_and(|n| n == var) {
return to.clone(); return to.clone();
} }
self.map(|tp| tp.substitute(var, to)) self.map(&mut |tp| tp.substitute(var, to))
} }
pub fn replace(self, target: &TyParam, to: &TyParam) -> TyParam { pub fn replace(self, target: &TyParam, to: &TyParam) -> TyParam {
@ -1546,7 +1546,7 @@ impl TyParam {
match self { match self {
TyParam::Type(t) => TyParam::t(t._replace_tp(target, to)), TyParam::Type(t) => TyParam::t(t._replace_tp(target, to)),
TyParam::Value(val) => TyParam::value(val.replace_tp(target, to)), TyParam::Value(val) => TyParam::value(val.replace_tp(target, to)),
self_ => self_.map(|tp| tp._replace(target, to)), self_ => self_.map(&mut |tp| tp._replace(target, to)),
} }
} }
@ -1561,7 +1561,7 @@ impl TyParam {
Self::Type(t) => Self::t(t._replace(target, to)), Self::Type(t) => Self::t(t._replace(target, to)),
Self::Erased(t) => Self::erased(t._replace(target, to)), Self::Erased(t) => Self::erased(t._replace(target, to)),
Self::Value(val) => Self::Value(val.replace_t(target, to)), Self::Value(val) => Self::Value(val.replace_t(target, to)),
_ => self.map(|tp| tp.replace_t(target, to)), _ => self.map(&mut |tp| tp.replace_t(target, to)),
} }
} }
@ -1592,8 +1592,11 @@ impl TyParam {
if self.addr_eq(to) { if self.addr_eq(to) {
return; return;
} }
if DEBUG_MODE && self.level() == Some(GENERIC_LEVEL) { if self.level() == Some(GENERIC_LEVEL) {
panic!("{self} is fixed"); /*if DEBUG_MODE {
panic!("{self} is fixed");
}*/
return;
} }
match self { match self {
Self::FreeVar(fv) => fv.link(to), Self::FreeVar(fv) => fv.link(to),
@ -1858,7 +1861,8 @@ impl TyParam {
} }
} }
pub fn map(self, f: impl Fn(TyParam) -> TyParam + Copy) -> TyParam { /// For recursive function
pub fn map(self, f: &mut impl FnMut(TyParam) -> TyParam) -> TyParam {
match self { match self {
TyParam::FreeVar(fv) if fv.is_linked() => f(fv.unwrap_linked()), TyParam::FreeVar(fv) if fv.is_linked() => f(fv.unwrap_linked()),
TyParam::App { name, args } => { TyParam::App { name, args } => {
@ -1901,15 +1905,12 @@ impl TyParam {
obj: Box::new(f(*obj)), obj: Box::new(f(*obj)),
attr, attr,
}, },
TyParam::ProjCall { obj, attr, args } => { TyParam::ProjCall { obj, attr, args } => TyParam::ProjCall {
let new_args = args.into_iter().map(f).collect::<Vec<_>>(); obj: Box::new(f(*obj)),
TyParam::ProjCall { attr,
obj: Box::new(f(*obj)), args: args.into_iter().map(f).collect::<Vec<_>>(),
attr, },
args: new_args, TyParam::Value(val) => TyParam::Value(val.map_tp(f)),
}
}
TyParam::Value(val) => TyParam::Value(val.map_t(&mut |t| t.map_tp(f))),
self_ => self_, self_ => self_,
} }
} }

View file

@ -15,7 +15,7 @@ use erg_common::python_util::PythonVersion;
use erg_common::serialize::*; use erg_common::serialize::*;
use erg_common::set::Set; use erg_common::set::Set;
use erg_common::traits::LimitedDisplay; use erg_common::traits::LimitedDisplay;
use erg_common::{dict, fmt_iter, impl_display_from_debug, log, switch_lang}; use erg_common::{dict, fmt_iter, log, switch_lang};
use erg_common::{ArcArray, Str}; use erg_common::{ArcArray, Str};
use erg_parser::ast::{ConstArgs, ConstExpr}; use erg_parser::ast::{ConstArgs, ConstExpr};
@ -377,12 +377,20 @@ impl GenTypeObj {
*self.typ_mut() = f(std::mem::take(self.typ_mut())); *self.typ_mut() = f(std::mem::take(self.typ_mut()));
} }
pub fn map_tp(&mut self, f: impl Fn(TyParam) -> TyParam + Copy) { pub fn map_tp(&mut self, f: &mut impl FnMut(TyParam) -> TyParam) {
*self.typ_mut() = std::mem::take(self.typ_mut()).map_tp(f); *self.typ_mut() = std::mem::take(self.typ_mut()).map_tp(f);
} }
pub fn try_map_t<E>(&mut self, f: impl FnOnce(Type) -> Result<Type, E>) -> Result<(), E> { pub fn try_map_t<E>(&mut self, f: impl FnOnce(Type) -> Result<Type, E>) -> Result<(), E> {
*self.typ_mut() = f(self.typ().clone())?; *self.typ_mut() = f(std::mem::take(self.typ_mut()))?;
Ok(())
}
pub fn try_map_tp<E>(
&mut self,
f: &mut impl FnMut(TyParam) -> Result<TyParam, E>,
) -> Result<(), E> {
*self.typ_mut() = std::mem::take(self.typ_mut()).try_map_tp(f)?;
Ok(()) Ok(())
} }
} }
@ -493,7 +501,7 @@ impl TypeObj {
} }
} }
pub fn map_tp(&mut self, f: impl Fn(TyParam) -> TyParam + Copy) { pub fn map_tp(&mut self, f: &mut impl FnMut(TyParam) -> TyParam) {
match self { match self {
TypeObj::Builtin { t, .. } => *t = std::mem::take(t).map_tp(f), TypeObj::Builtin { t, .. } => *t = std::mem::take(t).map_tp(f),
TypeObj::Generated(t) => t.map_tp(f), TypeObj::Generated(t) => t.map_tp(f),
@ -505,25 +513,49 @@ impl TypeObj {
self self
} }
pub fn mapped_tp(mut self, f: impl Fn(TyParam) -> TyParam + Copy) -> Self { pub fn mapped_tp(mut self, f: &mut impl FnMut(TyParam) -> TyParam) -> Self {
self.map_tp(f); self.map_tp(f);
self self
} }
pub fn try_map_t<E>(&mut self, f: impl FnOnce(Type) -> Result<Type, E>) -> Result<(), E> { pub fn try_map_t<E>(&mut self, f: &mut impl FnMut(Type) -> Result<Type, E>) -> Result<(), E> {
match self { match self {
TypeObj::Builtin { t, .. } => { TypeObj::Builtin { t, .. } => {
*t = f(t.clone())?; *t = f(std::mem::take(t))?;
Ok(()) Ok(())
} }
TypeObj::Generated(t) => t.try_map_t(f), TypeObj::Generated(t) => t.try_map_t(f),
} }
} }
pub fn try_mapped_t<E>(mut self, f: impl FnOnce(Type) -> Result<Type, E>) -> Result<Self, E> { pub fn try_mapped_t<E>(
mut self,
f: &mut impl FnMut(Type) -> Result<Type, E>,
) -> Result<Self, E> {
self.try_map_t(f)?; self.try_map_t(f)?;
Ok(self) Ok(self)
} }
pub fn try_map_tp<E>(
&mut self,
f: &mut impl FnMut(TyParam) -> Result<TyParam, E>,
) -> Result<(), E> {
match self {
TypeObj::Builtin { t, .. } => {
*t = std::mem::take(t).try_map_tp(f)?;
Ok(())
}
TypeObj::Generated(t) => t.try_map_tp(f),
}
}
pub fn try_mapped_tp<E>(
mut self,
f: &mut impl FnMut(TyParam) -> Result<TyParam, E>,
) -> Result<Self, E> {
self.try_map_tp(f)?;
Ok(self)
}
} }
/// 値オブジェクト /// 値オブジェクト
@ -558,6 +590,24 @@ pub enum ValueObj {
Failure, // placeholder for illegal values Failure, // placeholder for illegal values
} }
#[macro_export]
macro_rules! mono_value_pattern {
() => {
$crate::ty::ValueObj::Int(_)
| $crate::ty::ValueObj::Nat(_)
| $crate::ty::ValueObj::Float(_)
| $crate::ty::ValueObj::Inf
| $crate::ty::ValueObj::NegInf
| $crate::ty::ValueObj::Bool(_)
| $crate::ty::ValueObj::Str(_)
| $crate::ty::ValueObj::Code(_)
| $crate::ty::ValueObj::None
| $crate::ty::ValueObj::NotImplemented
| $crate::ty::ValueObj::Ellipsis
| $crate::ty::ValueObj::Failure
};
}
impl fmt::Debug for ValueObj { impl fmt::Debug for ValueObj {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
@ -630,8 +680,8 @@ impl fmt::Debug for ValueObj {
} }
write!(f, "}}") write!(f, "}}")
} }
Self::Subr(subr) => write!(f, "{subr}"), Self::Subr(subr) => subr.fmt(f),
Self::Type(t) => write!(f, "{t}"), Self::Type(t) => t.fmt(f),
Self::None => write!(f, "None"), Self::None => write!(f, "None"),
Self::Ellipsis => write!(f, "Ellipsis"), Self::Ellipsis => write!(f, "Ellipsis"),
Self::NotImplemented => write!(f, "NotImplemented"), Self::NotImplemented => write!(f, "NotImplemented"),
@ -642,7 +692,89 @@ impl fmt::Debug for ValueObj {
} }
} }
impl_display_from_debug!(ValueObj); impl fmt::Display for ValueObj {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Int(i) => {
if cfg!(feature = "debug") {
write!(f, "Int({i})")
} else {
write!(f, "{i}")
}
}
Self::Nat(n) => {
if cfg!(feature = "debug") {
write!(f, "Nat({n})")
} else {
write!(f, "{n}")
}
}
Self::Float(fl) => {
// In Rust, .0 is shown omitted.
if fl.fract() < 1e-10 {
write!(f, "{fl:.1}")?;
} else {
write!(f, "{fl}")?;
}
if cfg!(feature = "debug") {
write!(f, "f64")?;
}
Ok(())
}
Self::Str(s) => write!(f, "\"{}\"", s.escape()),
Self::Bool(b) => {
if *b {
write!(f, "True")
} else {
write!(f, "False")
}
}
Self::List(lis) => write!(f, "[{}]", fmt_iter(lis.iter())),
Self::UnsizedList(elem) => write!(f, "[{elem}; _]"),
Self::Dict(dict) => {
write!(f, "{{")?;
for (i, (k, v)) in dict.iter().enumerate() {
if i != 0 {
write!(f, ", ")?;
}
write!(f, "{k}: {v}")?;
}
write!(f, "}}")
}
Self::Tuple(tup) => write!(f, "({})", fmt_iter(tup.iter())),
Self::Set(st) => write!(f, "{{{}}}", fmt_iter(st.iter())),
Self::Code(code) => write!(f, "{code}"),
Self::Record(rec) => {
write!(f, "{{")?;
for (i, (k, v)) in rec.iter().enumerate() {
if i != 0 {
write!(f, "; ")?;
}
write!(f, "{k} = {v}")?;
}
write!(f, "}}")
}
Self::DataClass { name, fields } => {
write!(f, "{name} {{")?;
for (i, (k, v)) in fields.iter().enumerate() {
if i != 0 {
write!(f, "; ")?;
}
write!(f, "{k} = {v}")?;
}
write!(f, "}}")
}
Self::Subr(subr) => subr.fmt(f),
Self::Type(t) => t.fmt(f),
Self::None => write!(f, "None"),
Self::Ellipsis => write!(f, "Ellipsis"),
Self::NotImplemented => write!(f, "NotImplemented"),
Self::NegInf => write!(f, "-Inf"),
Self::Inf => write!(f, "Inf"),
Self::Failure => write!(f, "<failure>"),
}
}
}
impl LimitedDisplay for ValueObj { impl LimitedDisplay for ValueObj {
fn limited_fmt<W: std::fmt::Write>(&self, f: &mut W, limit: isize) -> std::fmt::Result { fn limited_fmt<W: std::fmt::Write>(&self, f: &mut W, limit: isize) -> std::fmt::Result {
@ -1652,7 +1784,7 @@ impl ValueObj {
name, name,
fields: fields.into_iter().map(|(k, v)| (k, v.map_t(f))).collect(), fields: fields.into_iter().map(|(k, v)| (k, v.map_t(f))).collect(),
}, },
ValueObj::UnsizedList(elem) => ValueObj::UnsizedList(Box::new(elem.clone().map_t(f))), ValueObj::UnsizedList(elem) => ValueObj::UnsizedList(Box::new(elem.map_t(f))),
self_ => self_, self_ => self_,
} }
} }
@ -1692,14 +1824,12 @@ impl ValueObj {
.map(|(k, v)| Ok((k, v.try_map_t(f)?))) .map(|(k, v)| Ok((k, v.try_map_t(f)?)))
.collect::<Result<Dict<_, _>, _>>()?, .collect::<Result<Dict<_, _>, _>>()?,
}), }),
ValueObj::UnsizedList(elem) => { ValueObj::UnsizedList(elem) => Ok(ValueObj::UnsizedList(Box::new(elem.try_map_t(f)?))),
Ok(ValueObj::UnsizedList(Box::new(elem.clone().try_map_t(f)?)))
}
self_ => Ok(self_), self_ => Ok(self_),
} }
} }
pub fn map_tp(self, f: impl Fn(TyParam) -> TyParam + Copy) -> Self { pub fn map_tp(self, f: &mut impl FnMut(TyParam) -> TyParam) -> Self {
match self { match self {
ValueObj::Type(obj) => ValueObj::Type(obj.mapped_tp(f)), ValueObj::Type(obj) => ValueObj::Type(obj.mapped_tp(f)),
ValueObj::List(lis) => { ValueObj::List(lis) => {
@ -1721,11 +1851,54 @@ impl ValueObj {
name, name,
fields: fields.into_iter().map(|(k, v)| (k, v.map_tp(f))).collect(), fields: fields.into_iter().map(|(k, v)| (k, v.map_tp(f))).collect(),
}, },
ValueObj::UnsizedList(elem) => ValueObj::UnsizedList(Box::new(elem.clone().map_tp(f))), ValueObj::UnsizedList(elem) => ValueObj::UnsizedList(Box::new(elem.map_tp(f))),
self_ => self_, self_ => self_,
} }
} }
pub fn try_map_tp<E>(
self,
f: &mut impl FnMut(TyParam) -> Result<TyParam, E>,
) -> Result<Self, E> {
match self {
ValueObj::Type(obj) => Ok(ValueObj::Type(obj.try_mapped_tp(f)?)),
ValueObj::List(lis) => Ok(ValueObj::List(
lis.iter()
.map(|v| v.clone().try_map_tp(f))
.collect::<Result<Arc<_>, _>>()?,
)),
ValueObj::Tuple(tup) => Ok(ValueObj::Tuple(
tup.iter()
.map(|v| v.clone().try_map_tp(f))
.collect::<Result<Arc<_>, _>>()?,
)),
ValueObj::Set(st) => Ok(ValueObj::Set(
st.into_iter()
.map(|v| v.try_map_tp(f))
.collect::<Result<Set<_>, _>>()?,
)),
ValueObj::Dict(dict) => Ok(ValueObj::Dict(
dict.into_iter()
.map(|(k, v)| Ok((k.try_map_tp(f)?, v.try_map_tp(f)?)))
.collect::<Result<Dict<_, _>, _>>()?,
)),
ValueObj::Record(rec) => Ok(ValueObj::Record(
rec.into_iter()
.map(|(k, v)| Ok((k, v.try_map_tp(f)?)))
.collect::<Result<Dict<_, _>, _>>()?,
)),
ValueObj::DataClass { name, fields } => Ok(ValueObj::DataClass {
name,
fields: fields
.into_iter()
.map(|(k, v)| Ok((k, v.try_map_tp(f)?)))
.collect::<Result<Dict<_, _>, _>>()?,
}),
ValueObj::UnsizedList(elem) => Ok(ValueObj::UnsizedList(Box::new(elem.try_map_tp(f)?))),
self_ => Ok(self_),
}
}
pub fn replace_t(self, target: &Type, to: &Type) -> Self { pub fn replace_t(self, target: &Type, to: &Type) -> Self {
self.map_t(&mut |t| t._replace(target, to)) self.map_t(&mut |t| t._replace(target, to))
} }