chore: add Predicate::{map_t, map_tp}

This commit is contained in:
Shunsuke Shibayama 2024-08-23 12:52:44 +09:00
parent 837414929c
commit 7a960f2cbb
8 changed files with 333 additions and 74 deletions

View file

@ -1968,15 +1968,17 @@ impl Context {
TyParam::erased(t)
}
},
TyParam::Value(ValueObj::Type(mut t)) => {
match t.try_map_t(|t| self.eval_t_params(t, self.level, &())) {
Ok(_) => {}
TyParam::Value(val) => {
match val
.clone()
.try_map_t(&mut |t| self.eval_t_params(t, self.level, &()))
{
Ok(val) => TyParam::Value(val),
Err((_t, es)) => {
errs.extend(es);
*t.typ_mut() = _t;
TyParam::Value(val)
}
}
TyParam::Value(ValueObj::Type(t))
}
TyParam::ProjCall { obj, attr, args } => {
match self.eval_proj_call(*obj, attr, args, &()) {
@ -1994,7 +1996,6 @@ impl Context {
return Err((TyParam::Failure, errs));
}
},
TyParam::Value(_) => p.clone(),
other => {
errs.push(EvalError::feature_error(
self.cfg.input.clone(),

View file

@ -45,9 +45,7 @@ impl Generalizer {
fn generalize_tp(&mut self, free: TyParam, uninit: bool) -> TyParam {
match free {
TyParam::Type(t) => TyParam::t(self.generalize_t(*t, uninit)),
TyParam::Value(ValueObj::Type(t)) => {
TyParam::t(self.generalize_t(t.into_typ(), uninit))
}
TyParam::Value(val) => TyParam::Value(val.map_t(&mut |t| self.generalize_t(t, uninit))),
TyParam::FreeVar(fv) if fv.is_generalized() => TyParam::FreeVar(fv),
TyParam::FreeVar(fv) if fv.is_linked() => {
let tp = fv.crack().clone();
@ -328,9 +326,8 @@ impl Generalizer {
fn generalize_pred(&mut self, pred: Predicate, uninit: bool) -> Predicate {
match pred {
Predicate::Const(_) | Predicate::Failure => pred,
Predicate::Value(ValueObj::Type(mut typ)) => {
*typ.typ_mut() = self.generalize_t(mem::take(typ.typ_mut()), uninit);
Predicate::Value(ValueObj::Type(typ))
Predicate::Value(val) => {
Predicate::Value(val.map_t(&mut |t| self.generalize_t(t, uninit)))
}
Predicate::Call {
receiver,
@ -348,7 +345,6 @@ impl Generalizer {
let receiver = self.generalize_tp(receiver, uninit);
Predicate::attr(receiver, name)
}
Predicate::Value(_) => pred,
Predicate::GeneralEqual { lhs, rhs } => {
let lhs = self.generalize_pred(*lhs, uninit);
let rhs = self.generalize_pred(*rhs, uninit);

View file

@ -578,15 +578,15 @@ impl Context {
let t = self.instantiate_t_inner(*t, tmp_tv_cache, loc)?;
Ok(TyParam::t(t))
}
TyParam::Value(ValueObj::Type(t)) => {
let t = self.instantiate_t_inner(t.into_typ(), tmp_tv_cache, loc)?;
Ok(TyParam::t(t))
TyParam::Value(val) => {
let val = val.try_map_t(&mut |t| self.instantiate_t_inner(t, tmp_tv_cache, loc))?;
Ok(TyParam::Value(val))
}
TyParam::Erased(t) => {
let t = self.instantiate_t_inner(*t, tmp_tv_cache, loc)?;
Ok(TyParam::Erased(Box::new(t)))
}
p @ (TyParam::Value(_) | TyParam::Mono(_) | TyParam::FreeVar(_)) => Ok(p),
p @ (TyParam::Mono(_) | TyParam::FreeVar(_)) => Ok(p),
other => {
type_feature_error!(
self,

View file

@ -317,6 +317,22 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> {
}
Ok(())
}
(ValueObj::Set(sub), ValueObj::Set(sup)) => {
if sub.len() == 1 && sup.len() == 1 {
let sub = sub.iter().next().unwrap();
let sup = sup.iter().next().unwrap();
self.sub_unify_value(sub, sup)?;
Ok(())
} else {
Err(TyCheckErrors::from(TyCheckError::feature_error(
self.ctx.cfg.input.clone(),
line!() as usize,
self.loc.loc(),
&format!("unifying {sub} and {sup}"),
self.ctx.caused_by(),
)))
}
}
(ValueObj::Record(sub), ValueObj::Record(sup)) => {
for (sub_k, sub_v) in sub.iter() {
if let Some(sup_v) = sup.get(sub_k) {

View file

@ -303,7 +303,7 @@ impl TryFrom<Type> for SubrType {
type Error = ();
fn try_from(t: Type) -> Result<Self, ()> {
match t {
Type::FreeVar(fv) if fv.is_linked() => Self::try_from(fv.crack().clone()),
Type::FreeVar(fv) if fv.is_linked() => Self::try_from(fv.unwrap_linked()),
Type::Subr(st) => Ok(st),
Type::Quantified(quant) => SubrType::try_from(*quant),
Type::Refinement(refine) => Self::try_from(*refine.t),
@ -2829,8 +2829,9 @@ impl Type {
Self::Poly { params, .. } => params.iter().any(|tp| tp.contains_type(target)),
Self::Quantified(t) => t.contains_type(target),
Self::Subr(subr) => subr.contains_type(target),
// TODO: preds
Self::Refinement(refine) => refine.t.contains_type(target),
Self::Refinement(refine) => {
refine.t.contains_type(target) || refine.pred.contains_t(target)
}
Self::Structural(ty) => ty.contains_type(target),
Self::Proj { lhs, .. } => lhs.contains_type(target),
Self::ProjCall { lhs, args, .. } => {
@ -2929,7 +2930,9 @@ impl Type {
Self::Poly { params, .. } => params.iter().any(|tp| tp.contains_type(self)),
Self::Quantified(t) => t.contains_type(self),
Self::Subr(subr) => subr.contains_type(self),
Self::Refinement(refine) => refine.t.contains_type(self),
Self::Refinement(refine) => {
refine.t.contains_type(self) || refine.pred.contains_t(self)
}
Self::Structural(ty) => ty.contains_type(self),
Self::Proj { lhs, .. } => lhs.contains_type(self),
Self::ProjCall { lhs, args, .. } => {
@ -3235,7 +3238,7 @@ impl Type {
/// ```
pub fn into_refinement(self) -> RefinementType {
match self {
Type::FreeVar(fv) if fv.is_linked() => fv.crack().clone().into_refinement(),
Type::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().into_refinement(),
Type::Nat => {
let var = FRESH_GEN.fresh_varname();
RefinementType::new(
@ -3289,7 +3292,7 @@ impl Type {
pub fn deconstruct_refinement(self) -> Result<(Str, Type, Predicate), Type> {
match self {
Type::FreeVar(fv) if fv.is_linked() => fv.crack().clone().deconstruct_refinement(),
Type::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().deconstruct_refinement(),
Type::Refinement(r) => Ok(r.deconstruct()),
_ => Err(self),
}
@ -3993,6 +3996,7 @@ impl Type {
Self::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().eliminate_recursion(target),
Self::Refinement(mut refine) => {
refine.t = Box::new(refine.t.eliminate_recursion(target));
refine.pred = Box::new(refine.pred.map_t(&mut |t| t.eliminate_recursion(target)));
Self::Refinement(refine)
}
Self::Record(mut rec) => {
@ -4138,7 +4142,7 @@ impl Type {
self = to.clone();
}
match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().clone()._replace(target, to),
Self::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked()._replace(target, to),
Self::FreeVar(fv) => {
let fv_clone = fv.deep_clone();
if let Some((sub, sup)) = fv_clone.get_subsup() {
@ -4157,6 +4161,7 @@ impl Type {
}
Self::Refinement(mut refine) => {
refine.t = Box::new(refine.t._replace(target, to));
refine.pred = Box::new(refine.pred._replace_t(target, to));
Self::Refinement(refine)
}
Self::Record(mut rec) => {
@ -4224,7 +4229,7 @@ impl Type {
fn _replace_tp(self, target: &TyParam, to: &TyParam) -> Type {
match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().clone()._replace_tp(target, to),
Self::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked()._replace_tp(target, to),
Self::FreeVar(fv) => {
let fv_clone = fv.deep_clone();
if let Some((sub, sup)) = fv_clone.get_subsup() {
@ -4245,7 +4250,7 @@ impl Type {
}
Self::Refinement(mut refine) => {
refine.t = Box::new(refine.t._replace_tp(target, to));
// refine.pred = refine.pred.replace_tp(target, to);
refine.pred = Box::new(refine.pred._replace_tp(target, to));
Self::Refinement(refine)
}
Self::Record(mut rec) => {
@ -4328,7 +4333,7 @@ impl Type {
}
Self::Refinement(mut refine) => {
refine.t = Box::new(refine.t.map_tp(f));
// refine.pred = refine.pred.replace_tp(target, to);
refine.pred = Box::new(refine.pred.map_tp(f));
Self::Refinement(refine)
}
Self::Record(mut rec) => {
@ -4387,7 +4392,7 @@ impl Type {
fn replace_param(self, target: &str, to: &str) -> Self {
match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().clone().replace_param(target, to),
Self::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().replace_param(target, to),
Self::Refinement(mut refine) => {
*refine.t = refine.t.replace_param(target, to);
Self::Refinement(refine)
@ -4412,11 +4417,16 @@ impl Type {
/// TyParam::Value(ValueObj::Type(_)) => TyParam::Type
pub fn normalize(self) -> Self {
match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().clone().normalize(),
Self::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().normalize(),
Self::Poly { name, params } => {
let params = params.into_iter().map(|tp| tp.normalize()).collect();
Self::Poly { name, params }
}
Self::Refinement(mut refine) => {
refine.t = Box::new(refine.t.normalize());
refine.pred = Box::new(refine.pred.map_t(&mut |t| t.normalize()));
Self::Refinement(refine)
}
Self::Subr(mut subr) => {
for nd in subr.non_default_params.iter_mut() {
*nd.typ_mut() = std::mem::take(nd.typ_mut()).normalize();
@ -4738,7 +4748,10 @@ impl Type {
fv.update_init();
}
// TODO: T(:> X, <: Y).dereference()
Self::Refinement(refine) => refine.t.dereference(),
Self::Refinement(refine) => {
refine.t.dereference();
refine.pred.dereference();
}
Self::Ref(t) => {
t.dereference();
}

View file

@ -10,8 +10,9 @@ use erg_common::{fmt_option, set, Str};
use super::free::{Constraint, HasLevel};
use super::typaram::TyParam;
use super::value::ValueObj;
use super::Type;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
pub enum Predicate {
Value(ValueObj), // True/False
Const(Str),
@ -63,6 +64,7 @@ pub enum Predicate {
Or(Box<Predicate>, Box<Predicate>),
And(Box<Predicate>, Box<Predicate>),
Not(Box<Predicate>),
#[default]
Failure,
}
@ -860,7 +862,7 @@ impl Predicate {
pub fn contains_value(&self, value: &ValueObj) -> bool {
match self {
Self::Value(v) => v == value,
Self::Value(v) => v.contains(value),
Self::Const(_) => false,
Self::Call { receiver, args, .. } => {
receiver.contains_value(value) || args.iter().any(|a| a.contains_value(value))
@ -886,8 +888,7 @@ impl Predicate {
pub fn contains_tp(&self, tp: &TyParam) -> bool {
match self {
Self::Value(_) | Self::Failure => false,
Self::Const(_) => false,
Self::Value(v) => v.contains_tp(tp),
Self::Call { receiver, args, .. } => {
receiver.contains_tp(tp) || args.iter().any(|a| a.contains_tp(tp))
}
@ -902,67 +903,159 @@ impl Predicate {
| Self::GeneralNotEqual { lhs, rhs } => lhs.contains_tp(tp) || rhs.contains_tp(tp),
Self::And(lhs, rhs) | Self::Or(lhs, rhs) => lhs.contains_tp(tp) || rhs.contains_tp(tp),
Self::Not(pred) => pred.contains_tp(tp),
_ => false,
}
}
pub fn replace_tp(self, target: &TyParam, to: &TyParam) -> Self {
pub fn contains_t(&self, t: &Type) -> bool {
match self {
Self::Value(_) | Self::Failure => self,
Self::Value(v) => v.contains_type(t),
Self::Call { receiver, args, .. } => {
receiver.contains_type(t) || args.iter().any(|a| a.contains_type(t))
}
Self::Attr { receiver, .. } => receiver.contains_type(t),
Self::Equal { rhs, .. }
| Self::GreaterEqual { rhs, .. }
| Self::LessEqual { rhs, .. }
| Self::NotEqual { rhs, .. } => rhs.contains_type(t),
Self::GeneralEqual { lhs, rhs }
| Self::GeneralLessEqual { lhs, rhs }
| Self::GeneralGreaterEqual { lhs, rhs }
| Self::GeneralNotEqual { lhs, rhs } => lhs.contains_t(t) || rhs.contains_t(t),
Self::And(lhs, rhs) | Self::Or(lhs, rhs) => lhs.contains_t(t) || rhs.contains_t(t),
Self::Not(pred) => pred.contains_t(t),
_ => false,
}
}
pub fn _replace_tp(self, target: &TyParam, to: &TyParam) -> Self {
self.map_tp(|tp| tp._replace(target, to))
}
pub fn replace_tp(self, target: &TyParam, to: &TyParam) -> Self {
self.map_tp(|tp| tp.replace(target, to))
}
pub fn _replace_t(self, target: &Type, to: &Type) -> Self {
self.map_t(&mut |t| t._replace(target, to))
}
pub fn dereference(&mut self) {
*self = std::mem::take(self).map_t(&mut |mut t| {
t.dereference();
t
});
}
pub fn map_t(self, f: &mut impl FnMut(Type) -> Type) -> Self {
match self {
Self::Value(val) => Self::Value(val.map_t(f)),
Self::Const(_) => self,
Self::Call {
receiver,
args,
name,
} => Self::Call {
receiver: receiver.replace(target, to),
args: args.into_iter().map(|a| a.replace(target, to)).collect(),
receiver: receiver.map_t(f),
args: args.into_iter().map(|a| a.map_t(f)).collect(),
name,
},
Self::Attr { receiver, name } => Self::Attr {
receiver: receiver.replace(target, to),
receiver: receiver.map_t(f),
name,
},
Self::Equal { lhs, rhs } => Self::Equal {
lhs,
rhs: rhs.replace(target, to),
rhs: rhs.map_t(f),
},
Self::GreaterEqual { lhs, rhs } => Self::GreaterEqual {
lhs,
rhs: rhs.replace(target, to),
rhs: rhs.map_t(f),
},
Self::LessEqual { lhs, rhs } => Self::LessEqual {
lhs,
rhs: rhs.replace(target, to),
rhs: rhs.map_t(f),
},
Self::NotEqual { lhs, rhs } => Self::NotEqual {
lhs,
rhs: rhs.replace(target, to),
rhs: rhs.map_t(f),
},
Self::GeneralEqual { lhs, rhs } => Self::GeneralEqual {
lhs: Box::new(lhs.replace_tp(target, to)),
rhs: Box::new(rhs.replace_tp(target, to)),
lhs: Box::new(lhs.map_t(f)),
rhs: Box::new(rhs.map_t(f)),
},
Self::GeneralLessEqual { lhs, rhs } => Self::GeneralLessEqual {
lhs: Box::new(lhs.replace_tp(target, to)),
rhs: Box::new(rhs.replace_tp(target, to)),
lhs: Box::new(lhs.map_t(f)),
rhs: Box::new(rhs.map_t(f)),
},
Self::GeneralGreaterEqual { lhs, rhs } => Self::GeneralGreaterEqual {
lhs: Box::new(lhs.replace_tp(target, to)),
rhs: Box::new(rhs.replace_tp(target, to)),
lhs: Box::new(lhs.map_t(f)),
rhs: Box::new(rhs.map_t(f)),
},
Self::GeneralNotEqual { lhs, rhs } => Self::GeneralNotEqual {
lhs: Box::new(lhs.replace_tp(target, to)),
rhs: Box::new(rhs.replace_tp(target, to)),
lhs: Box::new(lhs.map_t(f)),
rhs: Box::new(rhs.map_t(f)),
},
Self::And(lhs, rhs) => Self::And(
Box::new(lhs.replace_tp(target, to)),
Box::new(rhs.replace_tp(target, to)),
),
Self::Or(lhs, rhs) => Self::Or(
Box::new(lhs.replace_tp(target, to)),
Box::new(rhs.replace_tp(target, to)),
),
Self::Not(pred) => Self::Not(Box::new(pred.replace_tp(target, to))),
Self::And(lhs, rhs) => Self::And(Box::new(lhs.map_t(f)), Box::new(rhs.map_t(f))),
Self::Or(lhs, rhs) => Self::Or(Box::new(lhs.map_t(f)), Box::new(rhs.map_t(f))),
Self::Not(pred) => Self::Not(Box::new(pred.map_t(f))),
_ => self,
}
}
pub fn map_tp(self, f: impl Fn(TyParam) -> TyParam + Copy) -> Self {
match self {
Self::Value(val) => Self::Value(val.map_tp(f)),
Self::Const(_) => self,
Self::Call {
receiver,
args,
name,
} => Self::Call {
receiver: receiver.map(f),
args: args.into_iter().map(|a| a.map(f)).collect(),
name,
},
Self::Attr { receiver, name } => Self::Attr {
receiver: receiver.map(f),
name,
},
Self::Equal { lhs, rhs } => Self::Equal {
lhs,
rhs: rhs.map(f),
},
Self::GreaterEqual { lhs, rhs } => Self::GreaterEqual {
lhs,
rhs: rhs.map(f),
},
Self::LessEqual { lhs, rhs } => Self::LessEqual {
lhs,
rhs: rhs.map(f),
},
Self::NotEqual { lhs, rhs } => Self::NotEqual {
lhs,
rhs: rhs.map(f),
},
Self::GeneralEqual { lhs, rhs } => Self::GeneralEqual {
lhs: Box::new(lhs.map_tp(f)),
rhs: Box::new(rhs.map_tp(f)),
},
Self::GeneralLessEqual { lhs, rhs } => Self::GeneralLessEqual {
lhs: Box::new(lhs.map_tp(f)),
rhs: Box::new(rhs.map_tp(f)),
},
Self::GeneralGreaterEqual { lhs, rhs } => Self::GeneralGreaterEqual {
lhs: Box::new(lhs.map_tp(f)),
rhs: Box::new(rhs.map_tp(f)),
},
Self::GeneralNotEqual { lhs, rhs } => Self::GeneralNotEqual {
lhs: Box::new(lhs.map_tp(f)),
rhs: Box::new(rhs.map_tp(f)),
},
Self::And(lhs, rhs) => Self::And(Box::new(lhs.map_tp(f)), Box::new(rhs.map_tp(f))),
Self::Or(lhs, rhs) => Self::Or(Box::new(lhs.map_tp(f)), Box::new(rhs.map_tp(f))),
Self::Not(pred) => Self::Not(Box::new(pred.map_tp(f))),
_ => self,
}
}
}

View file

@ -1913,6 +1913,61 @@ impl TyParam {
self_ => self_,
}
}
pub fn map_t(self, f: &mut impl FnMut(Type) -> Type) -> TyParam {
match self {
TyParam::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().map_t(f),
TyParam::App { name, args } => {
let new_args = args.into_iter().map(|tp| tp.map_t(f)).collect::<Vec<_>>();
TyParam::app(name, new_args)
}
TyParam::BinOp { op, lhs, rhs } => TyParam::bin(op, lhs.map_t(f), rhs.map_t(f)),
TyParam::UnaryOp { op, val } => TyParam::unary(op, val.map_t(f)),
TyParam::UnsizedList(elem) => TyParam::unsized_list(elem.map_t(f)),
TyParam::List(tps) => TyParam::List(tps.into_iter().map(|tp| tp.map_t(f)).collect()),
TyParam::Tuple(tps) => TyParam::Tuple(tps.into_iter().map(|tp| tp.map_t(f)).collect()),
TyParam::Set(tps) => TyParam::Set(tps.into_iter().map(|tp| tp.map_t(f)).collect()),
TyParam::Dict(tps) => {
let new_tps = tps
.into_iter()
.map(|(k, v)| (k.map_t(f), v.map_t(f)))
.collect();
TyParam::Dict(new_tps)
}
TyParam::Record(rec) => {
let new_rec = rec.into_iter().map(|(k, v)| (k, v.map_t(f))).collect();
TyParam::Record(new_rec)
}
TyParam::DataClass { name, fields } => {
let new_fields = fields.into_iter().map(|(k, v)| (k, v.map_t(f))).collect();
TyParam::DataClass {
name,
fields: new_fields,
}
}
TyParam::Lambda(lambda) => {
let new_body = lambda.body.into_iter().map(|tp| tp.map_t(f)).collect();
TyParam::Lambda(TyParamLambda {
body: new_body,
..lambda
})
}
TyParam::Proj { obj, attr } => TyParam::Proj {
obj: Box::new(obj.map_t(f)),
attr,
},
TyParam::ProjCall { obj, attr, args } => {
let new_args = args.into_iter().map(|tp| tp.map_t(f)).collect::<Vec<_>>();
TyParam::ProjCall {
obj: Box::new(obj.map_t(f)),
attr,
args: new_args,
}
}
TyParam::Value(val) => TyParam::Value(val.map_t(f)),
self_ => self_,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]

View file

@ -374,7 +374,11 @@ impl GenTypeObj {
}
pub fn map_t(&mut self, f: impl FnOnce(Type) -> Type) {
*self.typ_mut() = f(self.typ().clone());
*self.typ_mut() = f(std::mem::take(self.typ_mut()));
}
pub fn map_tp(&mut self, f: impl Fn(TyParam) -> TyParam + Copy) {
*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> {
@ -484,16 +488,28 @@ impl TypeObj {
pub fn map_t(&mut self, f: impl FnOnce(Type) -> Type) {
match self {
TypeObj::Builtin { t, .. } => *t = f(t.clone()),
TypeObj::Builtin { t, .. } => *t = f(std::mem::take(t)),
TypeObj::Generated(t) => t.map_t(f),
}
}
pub fn map_tp(&mut self, f: impl Fn(TyParam) -> TyParam + Copy) {
match self {
TypeObj::Builtin { t, .. } => *t = std::mem::take(t).map_tp(f),
TypeObj::Generated(t) => t.map_tp(f),
}
}
pub fn mapped_t(mut self, f: impl FnOnce(Type) -> Type) -> Self {
self.map_t(f);
self
}
pub fn mapped_tp(mut self, f: impl Fn(TyParam) -> TyParam + Copy) -> Self {
self.map_tp(f);
self
}
pub fn try_map_t<E>(&mut self, f: impl FnOnce(Type) -> Result<Type, E>) -> Result<(), E> {
match self {
TypeObj::Builtin { t, .. } => {
@ -503,6 +519,11 @@ impl TypeObj {
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> {
self.try_map_t(f)?;
Ok(self)
}
}
/// 値オブジェクト
@ -1618,29 +1639,93 @@ impl ValueObj {
ValueObj::Tuple(tup) => {
ValueObj::Tuple(tup.iter().map(|v| v.clone().map_t(f)).collect())
}
ValueObj::Set(st) => ValueObj::Set(st.iter().map(|v| v.clone().map_t(f)).collect()),
ValueObj::Set(st) => ValueObj::Set(st.into_iter().map(|v| v.map_t(f)).collect()),
ValueObj::Dict(dict) => ValueObj::Dict(
dict.iter()
.map(|(k, v)| (k.clone().map_t(f), v.clone().map_t(f)))
.collect(),
),
ValueObj::Record(rec) => ValueObj::Record(
rec.iter()
.map(|(k, v)| (k.clone(), v.clone().map_t(f)))
dict.into_iter()
.map(|(k, v)| (k.map_t(f), v.map_t(f)))
.collect(),
),
ValueObj::Record(rec) => {
ValueObj::Record(rec.into_iter().map(|(k, v)| (k, v.map_t(f))).collect())
}
ValueObj::DataClass { name, fields } => ValueObj::DataClass {
name,
fields: fields
.iter()
.map(|(k, v)| (k.clone(), v.clone().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))),
self_ => self_,
}
}
pub fn try_map_t<E>(self, f: &mut impl FnMut(Type) -> Result<Type, E>) -> Result<Self, E> {
match self {
ValueObj::Type(obj) => Ok(ValueObj::Type(obj.try_mapped_t(f)?)),
ValueObj::List(lis) => Ok(ValueObj::List(
lis.iter()
.map(|v| v.clone().try_map_t(f))
.collect::<Result<Arc<_>, _>>()?,
)),
ValueObj::Tuple(tup) => Ok(ValueObj::Tuple(
tup.iter()
.map(|v| v.clone().try_map_t(f))
.collect::<Result<Arc<_>, _>>()?,
)),
ValueObj::Set(st) => Ok(ValueObj::Set(
st.into_iter()
.map(|v| v.try_map_t(f))
.collect::<Result<Set<_>, _>>()?,
)),
ValueObj::Dict(dict) => Ok(ValueObj::Dict(
dict.into_iter()
.map(|(k, v)| Ok((k.try_map_t(f)?, v.try_map_t(f)?)))
.collect::<Result<Dict<_, _>, _>>()?,
)),
ValueObj::Record(rec) => Ok(ValueObj::Record(
rec.into_iter()
.map(|(k, v)| Ok((k, v.try_map_t(f)?)))
.collect::<Result<Dict<_, _>, _>>()?,
)),
ValueObj::DataClass { name, fields } => Ok(ValueObj::DataClass {
name,
fields: fields
.into_iter()
.map(|(k, v)| Ok((k, v.try_map_t(f)?)))
.collect::<Result<Dict<_, _>, _>>()?,
}),
ValueObj::UnsizedList(elem) => {
Ok(ValueObj::UnsizedList(Box::new(elem.clone().try_map_t(f)?)))
}
self_ => Ok(self_),
}
}
pub fn map_tp(self, f: impl Fn(TyParam) -> TyParam + Copy) -> Self {
match self {
ValueObj::Type(obj) => ValueObj::Type(obj.mapped_tp(f)),
ValueObj::List(lis) => {
ValueObj::List(lis.iter().map(|v| v.clone().map_tp(f)).collect())
}
ValueObj::Tuple(tup) => {
ValueObj::Tuple(tup.iter().map(|v| v.clone().map_tp(f)).collect())
}
ValueObj::Set(st) => ValueObj::Set(st.into_iter().map(|v| v.map_tp(f)).collect()),
ValueObj::Dict(dict) => ValueObj::Dict(
dict.into_iter()
.map(|(k, v)| (k.map_tp(f), v.map_tp(f)))
.collect(),
),
ValueObj::Record(rec) => {
ValueObj::Record(rec.into_iter().map(|(k, v)| (k, v.map_tp(f))).collect())
}
ValueObj::DataClass { name, fields } => ValueObj::DataClass {
name,
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))),
self_ => self_,
}
}
pub fn replace_t(self, target: &Type, to: &Type) -> Self {
self.map_t(&mut |t| t._replace(target, to))
}