mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-27 11:59:05 +00:00
chore: improve Type::replace_failure
This commit is contained in:
parent
13eaf8d3a7
commit
bc23f9d045
4 changed files with 454 additions and 27 deletions
|
@ -510,6 +510,21 @@ impl SubrType {
|
|||
|| self.return_t.contains_tp(target)
|
||||
}
|
||||
|
||||
pub fn contains_value(&self, target: &ValueObj) -> bool {
|
||||
self.non_default_params
|
||||
.iter()
|
||||
.any(|pt| pt.typ().contains_value(target))
|
||||
|| self
|
||||
.var_params
|
||||
.as_ref()
|
||||
.map_or(false, |pt| pt.typ().contains_value(target))
|
||||
|| self.default_params.iter().any(|pt| {
|
||||
pt.typ().contains_value(target)
|
||||
|| pt.default_typ().is_some_and(|t| t.contains_value(target))
|
||||
})
|
||||
|| self.return_t.contains_value(target)
|
||||
}
|
||||
|
||||
pub fn qvars(&self) -> Set<(Str, Constraint)> {
|
||||
let mut qvars = Set::new();
|
||||
for pt in self.non_default_params.iter() {
|
||||
|
@ -779,10 +794,36 @@ impl SubrType {
|
|||
*default = std::mem::take(default)._replace(target, to);
|
||||
}
|
||||
}
|
||||
if let Some(kw_var) = self.kw_var_params.as_mut() {
|
||||
*kw_var.as_mut().typ_mut() =
|
||||
std::mem::take(kw_var.as_mut().typ_mut())._replace(target, to);
|
||||
}
|
||||
self.return_t = Box::new(self.return_t._replace(target, to));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn _replace_tp(mut self, target: &TyParam, to: &TyParam) -> Self {
|
||||
for nd in self.non_default_params.iter_mut() {
|
||||
*nd.typ_mut() = std::mem::take(nd.typ_mut())._replace_tp(target, to);
|
||||
}
|
||||
if let Some(var) = self.var_params.as_mut() {
|
||||
*var.as_mut().typ_mut() =
|
||||
std::mem::take(var.as_mut().typ_mut())._replace_tp(target, to);
|
||||
}
|
||||
for d in self.default_params.iter_mut() {
|
||||
*d.typ_mut() = std::mem::take(d.typ_mut())._replace_tp(target, to);
|
||||
if let Some(default) = d.default_typ_mut() {
|
||||
*default = std::mem::take(default)._replace_tp(target, to);
|
||||
}
|
||||
}
|
||||
if let Some(kw_var) = self.kw_var_params.as_mut() {
|
||||
*kw_var.as_mut().typ_mut() =
|
||||
std::mem::take(kw_var.as_mut().typ_mut())._replace_tp(target, to);
|
||||
}
|
||||
self.return_t = Box::new(self.return_t._replace_tp(target, to));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn replace_params(mut self, target_and_to: Vec<(Str, Str)>) -> Self {
|
||||
for (target, to) in target_and_to {
|
||||
for nd in self.non_default_params.iter_mut() {
|
||||
|
@ -2138,6 +2179,24 @@ impl Type {
|
|||
Self::Structural(Box::new(self))
|
||||
}
|
||||
|
||||
pub fn bounded(sub: Type, sup: Type) -> Self {
|
||||
Self::Bounded {
|
||||
sub: Box::new(sub),
|
||||
sup: Box::new(sup),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_ref(self) -> Self {
|
||||
Self::Ref(Box::new(self))
|
||||
}
|
||||
|
||||
pub fn into_ref_mut(self, after: Option<Self>) -> Self {
|
||||
Self::RefMut {
|
||||
before: Box::new(self),
|
||||
after: after.map(Box::new),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_mono_value_class(&self) -> bool {
|
||||
match self {
|
||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_mono_value_class(),
|
||||
|
@ -2704,8 +2763,9 @@ impl Type {
|
|||
Self::Poly { params, .. } => params.iter().any(|tp| tp.contains_tp(target)),
|
||||
Self::Quantified(t) => t.contains_tp(target),
|
||||
Self::Subr(subr) => subr.contains_tp(target),
|
||||
// TODO: preds
|
||||
Self::Refinement(refine) => refine.t.contains_tp(target),
|
||||
Self::Refinement(refine) => {
|
||||
refine.t.contains_tp(target) || refine.pred.contains_tp(target)
|
||||
}
|
||||
Self::Structural(ty) => ty.contains_tp(target),
|
||||
Self::Proj { lhs, .. } => lhs.contains_tp(target),
|
||||
Self::ProjCall { lhs, args, .. } => {
|
||||
|
@ -2724,6 +2784,41 @@ impl Type {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn contains_value(&self, target: &ValueObj) -> bool {
|
||||
match self {
|
||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().contains_value(target),
|
||||
Self::Record(rec) => rec.iter().any(|(_, t)| t.contains_value(target)),
|
||||
Self::NamedTuple(rec) => rec.iter().any(|(_, t)| t.contains_value(target)),
|
||||
Self::Poly { params, .. } => params.iter().any(|tp| tp.contains_value(target)),
|
||||
Self::Quantified(t) => t.contains_value(target),
|
||||
Self::Subr(subr) => subr.contains_value(target),
|
||||
Self::Refinement(refine) => {
|
||||
refine.t.contains_value(target) || refine.pred.contains_value(target)
|
||||
}
|
||||
Self::Structural(ty) => ty.contains_value(target),
|
||||
Self::Proj { lhs, .. } => lhs.contains_value(target),
|
||||
Self::ProjCall { lhs, args, .. } => {
|
||||
lhs.contains_value(target) || args.iter().any(|t| t.contains_value(target))
|
||||
}
|
||||
Self::And(lhs, rhs) => lhs.contains_value(target) || rhs.contains_value(target),
|
||||
Self::Or(lhs, rhs) => lhs.contains_value(target) || rhs.contains_value(target),
|
||||
Self::Not(t) => t.contains_value(target),
|
||||
Self::Ref(t) => t.contains_value(target),
|
||||
Self::RefMut { before, after } => {
|
||||
before.contains_value(target)
|
||||
|| after.as_ref().map_or(false, |t| t.contains_value(target))
|
||||
}
|
||||
Self::Bounded { sub, sup } => sub.contains_value(target) || sup.contains_value(target),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains_failure(&self) -> bool {
|
||||
self.contains_tp(&TyParam::Failure)
|
||||
|| self.contains_type(&Type::Failure)
|
||||
|| self.contains_value(&ValueObj::Failure)
|
||||
}
|
||||
|
||||
pub fn is_recursive(&self) -> bool {
|
||||
match self {
|
||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_recursive(),
|
||||
|
@ -3768,11 +3863,11 @@ impl Type {
|
|||
}
|
||||
|
||||
/// ```erg
|
||||
/// (Failure -> Int).replace_failure() == (Obj -> Int)
|
||||
/// (Int -> Failure).replace_failure() == (Int -> Never)
|
||||
/// List(Failure, 3).replace_failure() == List(Never, 3)
|
||||
/// (Failure -> Int).replace_failure_type() == (Obj -> Int)
|
||||
/// (Int -> Failure).replace_failure_type() == (Int -> Never)
|
||||
/// List(Failure, 3).replace_failure_type() == List(Never, 3)
|
||||
/// ```
|
||||
pub fn replace_failure(&self) -> Type {
|
||||
pub fn replace_failure_type(&self) -> Type {
|
||||
match self {
|
||||
Self::Quantified(quant) => quant.replace_failure().quantify(),
|
||||
Self::Subr(subr) => {
|
||||
|
@ -3821,6 +3916,21 @@ impl Type {
|
|||
}
|
||||
}
|
||||
|
||||
/// ```erg
|
||||
/// Int.replace_failure() == Int
|
||||
/// K(Failure).replace_failure() == K(Never)
|
||||
/// {<failure>}.replace_failure() == Never
|
||||
/// K(<Failure>).replace_failure() == Never
|
||||
/// ```
|
||||
pub fn replace_failure(&self) -> Type {
|
||||
let self_ = self.replace_failure_type();
|
||||
if self_.contains_failure() {
|
||||
Self::Never
|
||||
} else {
|
||||
self_
|
||||
}
|
||||
}
|
||||
|
||||
fn _replace(mut self, target: &Type, to: &Type) -> Type {
|
||||
if self.structural_eq(target) {
|
||||
self = to.clone();
|
||||
|
@ -3910,6 +4020,92 @@ 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) => {
|
||||
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._replace_tp(target, to);
|
||||
let sup = sup._replace_tp(target, to);
|
||||
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._replace_tp(target, to)),
|
||||
true,
|
||||
);
|
||||
}
|
||||
Self::FreeVar(fv_clone)
|
||||
}
|
||||
Self::Refinement(mut refine) => {
|
||||
refine.t = Box::new(refine.t._replace_tp(target, to));
|
||||
// refine.pred = refine.pred.replace_tp(target, to);
|
||||
Self::Refinement(refine)
|
||||
}
|
||||
Self::Record(mut rec) => {
|
||||
for v in rec.values_mut() {
|
||||
*v = std::mem::take(v)._replace_tp(target, to);
|
||||
}
|
||||
Self::Record(rec)
|
||||
}
|
||||
Self::NamedTuple(mut r) => {
|
||||
for (_, v) in r.iter_mut() {
|
||||
*v = std::mem::take(v)._replace_tp(target, to);
|
||||
}
|
||||
Self::NamedTuple(r)
|
||||
}
|
||||
Self::Subr(subr) => Self::Subr(subr._replace_tp(target, to)),
|
||||
Self::Callable { param_ts, return_t } => {
|
||||
let param_ts = param_ts
|
||||
.into_iter()
|
||||
.map(|t| t._replace_tp(target, to))
|
||||
.collect();
|
||||
let return_t = Box::new(return_t._replace_tp(target, to));
|
||||
Self::Callable { param_ts, return_t }
|
||||
}
|
||||
Self::Quantified(quant) => quant._replace_tp(target, to).quantify(),
|
||||
Self::Poly { name, params } => {
|
||||
let params = params
|
||||
.into_iter()
|
||||
.map(|tp| tp._replace(target, to))
|
||||
.collect();
|
||||
Self::Poly { name, params }
|
||||
}
|
||||
Self::Ref(t) => Self::Ref(Box::new(t._replace_tp(target, to))),
|
||||
Self::RefMut { before, after } => Self::RefMut {
|
||||
before: Box::new(before._replace_tp(target, to)),
|
||||
after: after.map(|t| Box::new(t._replace_tp(target, to))),
|
||||
},
|
||||
Self::And(l, r) => l._replace_tp(target, to) & r._replace_tp(target, to),
|
||||
Self::Or(l, r) => l._replace_tp(target, to) | r._replace_tp(target, to),
|
||||
Self::Not(ty) => !ty._replace_tp(target, to),
|
||||
Self::Proj { lhs, rhs } => lhs._replace_tp(target, to).proj(rhs),
|
||||
Self::ProjCall {
|
||||
lhs,
|
||||
attr_name,
|
||||
args,
|
||||
} => {
|
||||
let args = args.into_iter().map(|tp| tp._replace(target, to)).collect();
|
||||
proj_call(lhs._replace(target, to), attr_name, args)
|
||||
}
|
||||
Self::Structural(ty) => ty._replace_tp(target, to).structuralize(),
|
||||
Self::Guard(guard) => Self::Guard(GuardType::new(
|
||||
guard.namespace,
|
||||
guard.target.clone(),
|
||||
guard.to._replace_tp(target, to),
|
||||
)),
|
||||
Self::Bounded { sub, sup } => Self::Bounded {
|
||||
sub: Box::new(sub._replace_tp(target, to)),
|
||||
sup: Box::new(sup._replace_tp(target, to)),
|
||||
},
|
||||
other => other,
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
|
@ -4415,23 +4611,43 @@ impl Type {
|
|||
}
|
||||
|
||||
pub struct ReplaceTable<'t> {
|
||||
rules: Vec<(&'t Type, &'t Type)>,
|
||||
type_rules: Vec<(&'t Type, &'t Type)>,
|
||||
tp_rules: Vec<(&'t TyParam, &'t TyParam)>,
|
||||
}
|
||||
|
||||
impl<'t> ReplaceTable<'t> {
|
||||
pub fn make(target: &'t Type, to: &'t Type) -> Self {
|
||||
let mut self_ = ReplaceTable { rules: vec![] };
|
||||
let mut self_ = ReplaceTable {
|
||||
type_rules: vec![],
|
||||
tp_rules: vec![],
|
||||
};
|
||||
self_.iterate(target, to);
|
||||
self_
|
||||
}
|
||||
|
||||
pub fn make_tp(target: &'t TyParam, to: &'t TyParam) -> Self {
|
||||
let mut self_ = ReplaceTable {
|
||||
type_rules: vec![],
|
||||
tp_rules: vec![],
|
||||
};
|
||||
self_.iterate_tp(target, to);
|
||||
self_
|
||||
}
|
||||
|
||||
pub fn replace(&self, mut ty: Type) -> Type {
|
||||
for (target, to) in self.rules.iter() {
|
||||
for (target, to) in self.type_rules.iter() {
|
||||
ty = ty._replace(target, to);
|
||||
}
|
||||
ty
|
||||
}
|
||||
|
||||
pub fn replace_tp(&self, mut tp: TyParam) -> TyParam {
|
||||
for (target, to) in self.tp_rules.iter() {
|
||||
tp = tp._replace(target, to);
|
||||
}
|
||||
tp
|
||||
}
|
||||
|
||||
fn iterate(&mut self, target: &'t Type, to: &'t Type) {
|
||||
match (target, to) {
|
||||
(
|
||||
|
@ -4530,7 +4746,7 @@ impl<'t> ReplaceTable<'t> {
|
|||
}
|
||||
_ => {}
|
||||
}
|
||||
self.rules.push((target, to));
|
||||
self.type_rules.push((target, to));
|
||||
}
|
||||
|
||||
fn iterate_tp(&mut self, target: &'t TyParam, to: &'t TyParam) {
|
||||
|
@ -4548,6 +4764,7 @@ impl<'t> ReplaceTable<'t> {
|
|||
}
|
||||
_ => {}
|
||||
}
|
||||
self.tp_rules.push((target, to));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -857,4 +857,112 @@ impl Predicate {
|
|||
Self::Not(pred) => pred.variables(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains_value(&self, value: &ValueObj) -> bool {
|
||||
match self {
|
||||
Self::Value(v) => v == value,
|
||||
Self::Const(_) => false,
|
||||
Self::Call { receiver, args, .. } => {
|
||||
receiver.contains_value(value) || args.iter().any(|a| a.contains_value(value))
|
||||
}
|
||||
Self::Attr { receiver, .. } => receiver.contains_value(value),
|
||||
Self::Equal { rhs, .. }
|
||||
| Self::GreaterEqual { rhs, .. }
|
||||
| Self::LessEqual { rhs, .. }
|
||||
| Self::NotEqual { rhs, .. } => rhs.contains_value(value),
|
||||
Self::GeneralEqual { lhs, rhs }
|
||||
| Self::GeneralLessEqual { lhs, rhs }
|
||||
| Self::GeneralGreaterEqual { lhs, rhs }
|
||||
| Self::GeneralNotEqual { lhs, rhs } => {
|
||||
lhs.contains_value(value) || rhs.contains_value(value)
|
||||
}
|
||||
Self::And(lhs, rhs) | Self::Or(lhs, rhs) => {
|
||||
lhs.contains_value(value) || rhs.contains_value(value)
|
||||
}
|
||||
Self::Not(pred) => pred.contains_value(value),
|
||||
Self::Failure => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains_tp(&self, tp: &TyParam) -> bool {
|
||||
match self {
|
||||
Self::Value(_) | Self::Failure => false,
|
||||
Self::Const(_) => false,
|
||||
Self::Call { receiver, args, .. } => {
|
||||
receiver.contains_tp(tp) || args.iter().any(|a| a.contains_tp(tp))
|
||||
}
|
||||
Self::Attr { receiver, .. } => receiver.contains_tp(tp),
|
||||
Self::Equal { rhs, .. }
|
||||
| Self::GreaterEqual { rhs, .. }
|
||||
| Self::LessEqual { rhs, .. }
|
||||
| Self::NotEqual { rhs, .. } => rhs.contains_tp(tp),
|
||||
Self::GeneralEqual { lhs, rhs }
|
||||
| Self::GeneralLessEqual { lhs, rhs }
|
||||
| Self::GeneralGreaterEqual { lhs, rhs }
|
||||
| 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),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn replace_tp(self, target: &TyParam, to: &TyParam) -> Self {
|
||||
match self {
|
||||
Self::Value(_) | Self::Failure => self,
|
||||
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(),
|
||||
name,
|
||||
},
|
||||
Self::Attr { receiver, name } => Self::Attr {
|
||||
receiver: receiver.replace(target, to),
|
||||
name,
|
||||
},
|
||||
Self::Equal { lhs, rhs } => Self::Equal {
|
||||
lhs,
|
||||
rhs: rhs.replace(target, to),
|
||||
},
|
||||
Self::GreaterEqual { lhs, rhs } => Self::GreaterEqual {
|
||||
lhs,
|
||||
rhs: rhs.replace(target, to),
|
||||
},
|
||||
Self::LessEqual { lhs, rhs } => Self::LessEqual {
|
||||
lhs,
|
||||
rhs: rhs.replace(target, to),
|
||||
},
|
||||
Self::NotEqual { lhs, rhs } => Self::NotEqual {
|
||||
lhs,
|
||||
rhs: rhs.replace(target, to),
|
||||
},
|
||||
Self::GeneralEqual { lhs, rhs } => Self::GeneralEqual {
|
||||
lhs: Box::new(lhs.replace_tp(target, to)),
|
||||
rhs: Box::new(rhs.replace_tp(target, to)),
|
||||
},
|
||||
Self::GeneralLessEqual { lhs, rhs } => Self::GeneralLessEqual {
|
||||
lhs: Box::new(lhs.replace_tp(target, to)),
|
||||
rhs: Box::new(rhs.replace_tp(target, to)),
|
||||
},
|
||||
Self::GeneralGreaterEqual { lhs, rhs } => Self::GeneralGreaterEqual {
|
||||
lhs: Box::new(lhs.replace_tp(target, to)),
|
||||
rhs: Box::new(rhs.replace_tp(target, to)),
|
||||
},
|
||||
Self::GeneralNotEqual { lhs, rhs } => Self::GeneralNotEqual {
|
||||
lhs: Box::new(lhs.replace_tp(target, to)),
|
||||
rhs: Box::new(rhs.replace_tp(target, to)),
|
||||
},
|
||||
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))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ use super::free::{
|
|||
CanbeFree, Constraint, FreeKind, FreeTyParam, FreeTyVar, HasLevel, Level, GENERIC_LEVEL,
|
||||
};
|
||||
use super::value::ValueObj;
|
||||
use super::{ConstSubr, Field, ParamTy, UserConstSubr};
|
||||
use super::{ConstSubr, Field, ParamTy, ReplaceTable, UserConstSubr};
|
||||
use super::{Type, CONTAINER_OMIT_THRESHOLD};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
|
@ -1324,6 +1324,41 @@ impl TyParam {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn contains_value(&self, target: &ValueObj) -> bool {
|
||||
match self {
|
||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().contains_value(target),
|
||||
Self::Type(t) => t.contains_value(target),
|
||||
Self::Erased(t) => t.contains_value(target),
|
||||
Self::Proj { obj, .. } => obj.contains_value(target),
|
||||
Self::ProjCall { obj, args, .. } => {
|
||||
obj.contains_value(target) || args.iter().any(|t| t.contains_value(target))
|
||||
}
|
||||
Self::List(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.contains_value(target)),
|
||||
Self::UnsizedList(elem) => elem.contains_value(target),
|
||||
Self::Set(ts) => ts.iter().any(|t| t.contains_value(target)),
|
||||
Self::Dict(ts) => ts
|
||||
.iter()
|
||||
.any(|(k, v)| k.contains_value(target) || v.contains_value(target)),
|
||||
Self::Record(rec) | Self::DataClass { fields: rec, .. } => {
|
||||
rec.iter().any(|(_, tp)| tp.contains_value(target))
|
||||
}
|
||||
Self::Lambda(lambda) => lambda.body.iter().any(|tp| tp.contains_value(target)),
|
||||
Self::UnaryOp { val, .. } => val.contains_value(target),
|
||||
Self::BinOp { lhs, rhs, .. } => {
|
||||
lhs.contains_value(target) || rhs.contains_value(target)
|
||||
}
|
||||
Self::App { args, .. } => args.iter().any(|p| p.contains_value(target)),
|
||||
Self::Value(val) => val.contains(target),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains_failure(&self) -> bool {
|
||||
self.contains_tp(&TyParam::Failure)
|
||||
|| self.contains_type(&Type::Failure)
|
||||
|| self.contains_value(&ValueObj::Failure)
|
||||
}
|
||||
|
||||
pub fn is_recursive(&self) -> bool {
|
||||
match self {
|
||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_recursive(),
|
||||
|
@ -1592,58 +1627,63 @@ impl TyParam {
|
|||
}
|
||||
|
||||
pub fn replace(self, target: &TyParam, to: &TyParam) -> TyParam {
|
||||
let table = ReplaceTable::make_tp(target, to);
|
||||
table.replace_tp(self)
|
||||
}
|
||||
|
||||
pub(crate) fn _replace(self, target: &TyParam, to: &TyParam) -> TyParam {
|
||||
if &self == target {
|
||||
return to.clone();
|
||||
}
|
||||
match self {
|
||||
TyParam::FreeVar(fv) if fv.is_linked() => fv.crack().clone().replace(target, to),
|
||||
TyParam::FreeVar(fv) if fv.is_linked() => fv.crack().clone()._replace(target, to),
|
||||
TyParam::App { name, args } => {
|
||||
let new_args = args
|
||||
.into_iter()
|
||||
.map(|arg| arg.replace(target, to))
|
||||
.map(|arg| arg._replace(target, to))
|
||||
.collect::<Vec<_>>();
|
||||
TyParam::app(name, new_args)
|
||||
}
|
||||
TyParam::BinOp { op, lhs, rhs } => {
|
||||
let new_lhs = lhs.replace(target, to);
|
||||
let new_rhs = rhs.replace(target, to);
|
||||
let new_lhs = lhs._replace(target, to);
|
||||
let new_rhs = rhs._replace(target, to);
|
||||
TyParam::bin(op, new_lhs, new_rhs)
|
||||
}
|
||||
TyParam::UnaryOp { op, val } => {
|
||||
let new_val = val.replace(target, to);
|
||||
let new_val = val._replace(target, to);
|
||||
TyParam::unary(op, new_val)
|
||||
}
|
||||
TyParam::UnsizedList(elem) => TyParam::unsized_list(elem.replace(target, to)),
|
||||
TyParam::UnsizedList(elem) => TyParam::unsized_list(elem._replace(target, to)),
|
||||
TyParam::List(tps) => {
|
||||
let new_tps = tps.into_iter().map(|t| t.replace(target, to)).collect();
|
||||
let new_tps = tps.into_iter().map(|t| t._replace(target, to)).collect();
|
||||
TyParam::List(new_tps)
|
||||
}
|
||||
TyParam::Tuple(tps) => {
|
||||
let new_tps = tps.into_iter().map(|t| t.replace(target, to)).collect();
|
||||
let new_tps = tps.into_iter().map(|t| t._replace(target, to)).collect();
|
||||
TyParam::Tuple(new_tps)
|
||||
}
|
||||
TyParam::Set(tps) => {
|
||||
let new_tps = tps.into_iter().map(|t| t.replace(target, to)).collect();
|
||||
let new_tps = tps.into_iter().map(|t| t._replace(target, to)).collect();
|
||||
TyParam::Set(new_tps)
|
||||
}
|
||||
TyParam::Dict(tps) => {
|
||||
let new_tps = tps
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k.replace(target, to), v.replace(target, to)))
|
||||
.map(|(k, v)| (k._replace(target, to), v._replace(target, to)))
|
||||
.collect();
|
||||
TyParam::Dict(new_tps)
|
||||
}
|
||||
TyParam::Record(rec) => {
|
||||
let new_rec = rec
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, v.replace(target, to)))
|
||||
.map(|(k, v)| (k, v._replace(target, to)))
|
||||
.collect();
|
||||
TyParam::Record(new_rec)
|
||||
}
|
||||
TyParam::DataClass { name, fields } => {
|
||||
let new_fields = fields
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, v.replace(target, to)))
|
||||
.map(|(k, v)| (k, v._replace(target, to)))
|
||||
.collect();
|
||||
TyParam::DataClass {
|
||||
name,
|
||||
|
@ -1654,7 +1694,7 @@ impl TyParam {
|
|||
let new_body = lambda
|
||||
.body
|
||||
.into_iter()
|
||||
.map(|tp| tp.replace(target, to))
|
||||
.map(|tp| tp._replace(target, to))
|
||||
.collect();
|
||||
TyParam::Lambda(TyParamLambda {
|
||||
body: new_body,
|
||||
|
@ -1662,17 +1702,17 @@ impl TyParam {
|
|||
})
|
||||
}
|
||||
TyParam::Proj { obj, attr } => {
|
||||
let new_obj = obj.replace(target, to);
|
||||
let new_obj = obj._replace(target, to);
|
||||
TyParam::Proj {
|
||||
obj: Box::new(new_obj),
|
||||
attr,
|
||||
}
|
||||
}
|
||||
TyParam::ProjCall { obj, attr, args } => {
|
||||
let new_obj = obj.replace(target, to);
|
||||
let new_obj = obj._replace(target, to);
|
||||
let new_args = args
|
||||
.into_iter()
|
||||
.map(|arg| arg.replace(target, to))
|
||||
.map(|arg| arg._replace(target, to))
|
||||
.collect::<Vec<_>>();
|
||||
TyParam::ProjCall {
|
||||
obj: Box::new(new_obj),
|
||||
|
@ -1680,6 +1720,8 @@ impl TyParam {
|
|||
args: new_args,
|
||||
}
|
||||
}
|
||||
TyParam::Type(t) => TyParam::t(t._replace_tp(target, to)),
|
||||
TyParam::Value(val) => TyParam::value(val.replace_tp(target, to)),
|
||||
self_ => self_,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1654,6 +1654,66 @@ impl ValueObj {
|
|||
self_ => self_,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn replace_tp(self, target: &TyParam, to: &TyParam) -> Self {
|
||||
match self {
|
||||
ValueObj::Type(obj) => ValueObj::Type(obj.mapped_t(|t| t._replace_tp(target, to))),
|
||||
ValueObj::List(lis) => ValueObj::List(
|
||||
lis.iter()
|
||||
.map(|v| v.clone().replace_tp(target, to))
|
||||
.collect(),
|
||||
),
|
||||
ValueObj::Tuple(tup) => ValueObj::Tuple(
|
||||
tup.iter()
|
||||
.map(|v| v.clone().replace_tp(target, to))
|
||||
.collect(),
|
||||
),
|
||||
ValueObj::Set(st) => ValueObj::Set(
|
||||
st.iter()
|
||||
.map(|v| v.clone().replace_tp(target, to))
|
||||
.collect(),
|
||||
),
|
||||
ValueObj::Dict(dict) => ValueObj::Dict(
|
||||
dict.iter()
|
||||
.map(|(k, v)| {
|
||||
(
|
||||
k.clone().replace_tp(target, to),
|
||||
v.clone().replace_tp(target, to),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
ValueObj::Record(rec) => ValueObj::Record(
|
||||
rec.iter()
|
||||
.map(|(k, v)| (k.clone(), v.clone().replace_tp(target, to)))
|
||||
.collect(),
|
||||
),
|
||||
ValueObj::DataClass { name, fields } => ValueObj::DataClass {
|
||||
name,
|
||||
fields: fields
|
||||
.iter()
|
||||
.map(|(k, v)| (k.clone(), v.clone().replace_tp(target, to)))
|
||||
.collect(),
|
||||
},
|
||||
ValueObj::UnsizedList(elem) => {
|
||||
ValueObj::UnsizedList(Box::new(elem.clone().replace_tp(target, to)))
|
||||
}
|
||||
self_ => self_,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains(&self, val: &ValueObj) -> bool {
|
||||
match self {
|
||||
ValueObj::List(lis) => lis.iter().any(|v| v.contains(val)),
|
||||
ValueObj::Tuple(tup) => tup.iter().any(|v| v.contains(val)),
|
||||
ValueObj::Set(st) => st.iter().any(|v| v.contains(val)),
|
||||
ValueObj::Dict(dict) => dict.iter().any(|(k, v)| k.contains(val) || v.contains(val)),
|
||||
ValueObj::Record(rec) => rec.iter().any(|(_, v)| v.contains(val)),
|
||||
ValueObj::DataClass { fields, .. } => fields.iter().any(|(_, v)| v.contains(val)),
|
||||
ValueObj::UnsizedList(elem) => elem.contains(val),
|
||||
_ => self == val,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod value_set {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue