mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-04 10:49:54 +00:00
chore: add Predicate::{map_t, map_tp}
This commit is contained in:
parent
837414929c
commit
7a960f2cbb
8 changed files with 333 additions and 74 deletions
|
@ -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(),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue