mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-04 02:39:20 +00:00
feat: support using attributes in predicate
This commit is contained in:
parent
47818e431e
commit
0bedeb51ab
6 changed files with 194 additions and 21 deletions
|
@ -1664,7 +1664,9 @@ impl Context {
|
|||
Predicate::Call { receiver, name, .. } => {
|
||||
let receiver_t = self.get_tp_t(receiver).unwrap_or(Obj);
|
||||
if let Some(name) = name {
|
||||
let ctx = self.get_nominal_type_ctx(&receiver_t).unwrap();
|
||||
let Some(ctx) = self.get_nominal_type_ctx(&receiver_t) else {
|
||||
return Obj;
|
||||
};
|
||||
if let Some((_, method)) = ctx.get_var_info(name) {
|
||||
method.t.return_t().cloned().unwrap_or(Obj)
|
||||
} else {
|
||||
|
@ -1674,6 +1676,17 @@ impl Context {
|
|||
receiver_t.return_t().cloned().unwrap_or(Obj)
|
||||
}
|
||||
}
|
||||
Predicate::Attr { receiver, name } => {
|
||||
let receiver_t = self.get_tp_t(receiver).unwrap_or(Obj);
|
||||
let Some(ctx) = self.get_nominal_type_ctx(&receiver_t) else {
|
||||
return Obj;
|
||||
};
|
||||
if let Some((_, field)) = ctx.get_var_info(name) {
|
||||
field.t.clone()
|
||||
} else {
|
||||
Obj
|
||||
}
|
||||
}
|
||||
// REVIEW
|
||||
Predicate::GeneralEqual { rhs, .. }
|
||||
| Predicate::GeneralGreaterEqual { rhs, .. }
|
||||
|
|
|
@ -1589,6 +1589,7 @@ impl Context {
|
|||
Ok(TyParam::Value(ValueObj::Type(t)))
|
||||
}
|
||||
TyParam::ProjCall { obj, attr, args } => self.eval_proj_call(*obj, attr, args, &()),
|
||||
TyParam::Proj { obj, attr } => self.eval_tp_proj(*obj, attr, &()),
|
||||
TyParam::Value(_) => Ok(p.clone()),
|
||||
other => feature_error!(self, Location::Unknown, &format!("evaluating {other}")),
|
||||
}
|
||||
|
@ -1951,6 +1952,51 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn eval_tp_proj(
|
||||
&self,
|
||||
lhs: TyParam,
|
||||
rhs: Str,
|
||||
t_loc: &impl Locational,
|
||||
) -> EvalResult<TyParam> {
|
||||
// in Methods
|
||||
if let Some(ctx) = lhs
|
||||
.qual_name()
|
||||
.and_then(|name| self.get_same_name_context(&name))
|
||||
{
|
||||
if let Some(value) = ctx.rec_get_const_obj(&rhs) {
|
||||
return Ok(TyParam::value(value.clone()));
|
||||
}
|
||||
}
|
||||
let ty_ctxs = match self
|
||||
.get_tp_t(&lhs)
|
||||
.ok()
|
||||
.and_then(|t| self.get_nominal_super_type_ctxs(&t))
|
||||
{
|
||||
Some(ty_ctxs) => ty_ctxs,
|
||||
None => {
|
||||
let errs = EvalErrors::from(EvalError::type_not_found(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
t_loc.loc(),
|
||||
self.caused_by(),
|
||||
&Type::Obj,
|
||||
));
|
||||
return Err(errs);
|
||||
}
|
||||
};
|
||||
for ty_ctx in ty_ctxs {
|
||||
if let Some(value) = ty_ctx.rec_get_const_obj(&rhs) {
|
||||
return Ok(TyParam::value(value.clone()));
|
||||
}
|
||||
for methods in ty_ctx.methods_list.iter() {
|
||||
if let Some(value) = methods.rec_get_const_obj(&rhs) {
|
||||
return Ok(TyParam::value(value.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(lhs.proj(rhs))
|
||||
}
|
||||
|
||||
/// ```erg
|
||||
/// TyParam::Type(Int) => Int
|
||||
/// [{1}, {2}, {3}] => [{1, 2, 3}; 3]
|
||||
|
@ -2750,6 +2796,10 @@ impl Context {
|
|||
feature_error!(self, Location::Unknown, "eval_pred: Predicate::Call")
|
||||
}
|
||||
}
|
||||
Predicate::Attr { receiver, name } => {
|
||||
let receiver = self.eval_tp(receiver)?;
|
||||
Ok(Predicate::attr(receiver, name))
|
||||
}
|
||||
Predicate::GeneralEqual { lhs, rhs } => {
|
||||
match (self.eval_pred(*lhs)?, self.eval_pred(*rhs)?) {
|
||||
(Predicate::Value(lhs), Predicate::Value(rhs)) => {
|
||||
|
|
|
@ -335,6 +335,10 @@ impl Generalizer {
|
|||
}
|
||||
Predicate::call(receiver, name, new_args)
|
||||
}
|
||||
Predicate::Attr { receiver, name } => {
|
||||
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);
|
||||
|
|
|
@ -1577,6 +1577,10 @@ impl Context {
|
|||
self.inc_ref_local(local, self, tmp_tv_cache);
|
||||
Ok(Predicate::Const(local.inspect().clone()))
|
||||
}
|
||||
ast::ConstExpr::Accessor(ast::ConstAccessor::Attr(attr)) => {
|
||||
let obj = self.instantiate_const_expr(&attr.obj, None, tmp_tv_cache, false)?;
|
||||
Ok(Predicate::attr(obj, attr.name.inspect().clone()))
|
||||
}
|
||||
ast::ConstExpr::App(app) => {
|
||||
let receiver = self.instantiate_const_expr(&app.obj, None, tmp_tv_cache, false)?;
|
||||
let name = app.attr_name.as_ref().map(|n| n.inspect().to_owned());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue