mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-02 21:44:34 +00:00
WIP
This commit is contained in:
parent
2cf4b5aba8
commit
d62ec0f78f
2 changed files with 38 additions and 7 deletions
|
@ -59,6 +59,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(TyParam::MonoQVar(name), _other) | (_other, TyParam::MonoQVar(name)) => {
|
(TyParam::MonoQVar(name), _other) | (_other, TyParam::MonoQVar(name)) => {
|
||||||
|
log!(err "comparing '{name} and {_other}");
|
||||||
panic!("Not instantiated type parameter: {name}")
|
panic!("Not instantiated type parameter: {name}")
|
||||||
}
|
}
|
||||||
(TyParam::UnaryOp { op: lop, val: lval }, TyParam::UnaryOp { op: rop, val: rval }) => {
|
(TyParam::UnaryOp { op: lop, val: lval }, TyParam::UnaryOp { op: rop, val: rval }) => {
|
||||||
|
@ -673,22 +674,44 @@ impl Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn cyclic_supertype_of(&self, lhs: &FreeTyVar, rhs: &Type) -> bool {
|
pub(crate) fn cyclic_supertype_of(&self, lhs: &FreeTyVar, rhs: &Type) -> bool {
|
||||||
|
let (_, ty_ctx) = self.get_nominal_type_ctx(rhs).unwrap();
|
||||||
|
let subst_ctx = SubstContext::new(rhs, ty_ctx);
|
||||||
// if `rhs` is {S: Str | ... }, `defined_rhs` will be Str
|
// if `rhs` is {S: Str | ... }, `defined_rhs` will be Str
|
||||||
let defined_rhs = if let Some((defined_rhs, _)) = self.get_nominal_type_ctx(rhs) {
|
let defined_rhs = if let Some((defined_rhs, _ty_ctx)) = self.get_nominal_type_ctx(rhs) {
|
||||||
defined_rhs
|
if defined_rhs.has_qvar() {
|
||||||
|
subst_ctx
|
||||||
|
.substitute(defined_rhs.clone(), self, Location::Unknown)
|
||||||
|
.unwrap()
|
||||||
|
} else {
|
||||||
|
defined_rhs.clone()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
if let Some(super_traits) = self.get_nominal_super_trait_ctxs(rhs) {
|
if let Some(super_traits) = self.get_nominal_super_trait_ctxs(rhs) {
|
||||||
for (sup_trait, _) in super_traits {
|
for (sup_trait, _ty_ctx) in super_traits {
|
||||||
if self.sup_conforms(lhs, defined_rhs, sup_trait) {
|
let sup_trait = if sup_trait.has_qvar() {
|
||||||
|
subst_ctx
|
||||||
|
.substitute(sup_trait.clone(), self, Location::Unknown)
|
||||||
|
.unwrap()
|
||||||
|
} else {
|
||||||
|
sup_trait.clone()
|
||||||
|
};
|
||||||
|
if self.sup_conforms(lhs, &defined_rhs, &sup_trait) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(sup_classes) = self.get_nominal_super_class_ctxs(rhs) {
|
if let Some(sup_classes) = self.get_nominal_super_class_ctxs(rhs) {
|
||||||
for (sup_class, _) in sup_classes {
|
for (sup_class, _ty_ctx) in sup_classes {
|
||||||
if self.cyclic_supertype_of(lhs, sup_class) {
|
let sup_class = if sup_class.has_qvar() {
|
||||||
|
subst_ctx
|
||||||
|
.substitute(sup_class.clone(), self, Location::Unknown)
|
||||||
|
.unwrap()
|
||||||
|
} else {
|
||||||
|
sup_class.clone()
|
||||||
|
};
|
||||||
|
if self.cyclic_supertype_of(lhs, &sup_class) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,8 +106,13 @@ pub(crate) fn eval_lit(lit: &Literal) -> ValueObj {
|
||||||
ValueObj::from_str(t, lit.token.content.clone())
|
ValueObj::from_str(t, lit.token.content.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Instantiate the polymorphic type from the quantified state.
|
||||||
|
///
|
||||||
|
/// e.g.
|
||||||
|
/// ```
|
||||||
/// SubstContext::new(Array(?T, 0), Context(Array('T, 'N))) => SubstContext{ params: { 'T: ?T; 'N: 0 } } => ctx
|
/// SubstContext::new(Array(?T, 0), Context(Array('T, 'N))) => SubstContext{ params: { 'T: ?T; 'N: 0 } } => ctx
|
||||||
/// ctx.substitute(Array!('T; !'N)): Array(?T, !0)
|
/// ctx.substitute(Array!('T; !'N)): Array(?T, !0)
|
||||||
|
/// ```
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SubstContext {
|
pub struct SubstContext {
|
||||||
bounds: Set<TyBound>,
|
bounds: Set<TyBound>,
|
||||||
|
@ -125,6 +130,9 @@ impl fmt::Display for SubstContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SubstContext {
|
impl SubstContext {
|
||||||
|
/// `substituted` is used to obtain real argument information. So it must be instantiated as `Array(?T, 0)` and so on.
|
||||||
|
///
|
||||||
|
/// `ty_ctx` is used to obtain information on the names and variance of the parameters.
|
||||||
pub fn new(substituted: &Type, ty_ctx: &Context) -> Self {
|
pub fn new(substituted: &Type, ty_ctx: &Context) -> Self {
|
||||||
let bounds = ty_ctx.type_params_bounds();
|
let bounds = ty_ctx.type_params_bounds();
|
||||||
let param_names = ty_ctx.params.iter().map(|(opt_name, _)| {
|
let param_names = ty_ctx.params.iter().map(|(opt_name, _)| {
|
||||||
|
@ -135,7 +143,7 @@ impl SubstContext {
|
||||||
if param_names.len() != substituted.typarams().len() {
|
if param_names.len() != substituted.typarams().len() {
|
||||||
let param_names = param_names.collect::<Vec<_>>();
|
let param_names = param_names.collect::<Vec<_>>();
|
||||||
panic!(
|
panic!(
|
||||||
"{param_names:?} != {}",
|
"{param_names:?} != [{}]",
|
||||||
erg_common::fmt_vec(&substituted.typarams())
|
erg_common::fmt_vec(&substituted.typarams())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue