mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 00:01:16 +00:00
Solve and gen ability members that bind other able variables
This commit is contained in:
parent
5fe902b8d3
commit
b5efd830e5
6 changed files with 110 additions and 28 deletions
|
@ -578,12 +578,14 @@ fn resolve_abilities<'a>(
|
|||
|
||||
// What variables in the annotation are bound to the parent ability, and what variables
|
||||
// are bound to some other ability?
|
||||
let (variables_bound_to_ability, variables_bound_to_other_abilities): (Vec<_>, Vec<_>) =
|
||||
member_annot
|
||||
.introduced_variables
|
||||
.able
|
||||
.iter()
|
||||
.partition(|av| av.ability == loc_ability_name.value);
|
||||
let (variables_bound_to_ability, _variables_bound_to_other_abilities): (
|
||||
Vec<_>,
|
||||
Vec<_>,
|
||||
) = member_annot
|
||||
.introduced_variables
|
||||
.able
|
||||
.iter()
|
||||
.partition(|av| av.ability == loc_ability_name.value);
|
||||
|
||||
let mut bad_has_clauses = false;
|
||||
|
||||
|
@ -618,18 +620,6 @@ fn resolve_abilities<'a>(
|
|||
bad_has_clauses = true;
|
||||
}
|
||||
|
||||
if !variables_bound_to_other_abilities.is_empty() {
|
||||
// Disallow variables bound to other abilities, for now.
|
||||
for bad_variable in variables_bound_to_other_abilities.iter() {
|
||||
env.problem(Problem::AbilityMemberBindsExternalAbility {
|
||||
member: member_sym,
|
||||
ability: loc_ability_name.value,
|
||||
region: bad_variable.first_seen,
|
||||
});
|
||||
}
|
||||
bad_has_clauses = true;
|
||||
}
|
||||
|
||||
if bad_has_clauses {
|
||||
// Pretend the member isn't a part of the ability
|
||||
continue;
|
||||
|
|
|
@ -45,11 +45,12 @@ fn walk_def<V: Visitor>(visitor: &mut V, def: &Def) {
|
|||
..
|
||||
} = def;
|
||||
|
||||
visitor.visit_pattern(
|
||||
&loc_pattern.value,
|
||||
loc_pattern.region,
|
||||
loc_pattern.value.opt_var(),
|
||||
);
|
||||
let opt_var = match loc_pattern.value {
|
||||
Pattern::Identifier(..) | Pattern::AbilityMemberSpecialization { .. } => Some(*expr_var),
|
||||
_ => loc_pattern.value.opt_var(),
|
||||
};
|
||||
|
||||
visitor.visit_pattern(&loc_pattern.value, loc_pattern.region, opt_var);
|
||||
visitor.visit_expr(&loc_expr.value, loc_expr.region, *expr_var);
|
||||
if let Some(annot) = &annotation {
|
||||
visitor.visit_annotation(annot);
|
||||
|
@ -70,6 +71,9 @@ fn walk_expr<V: Visitor>(visitor: &mut V, expr: &Expr) {
|
|||
} => {
|
||||
walk_when(visitor, *cond_var, *expr_var, loc_cond, branches);
|
||||
}
|
||||
Expr::Call(f, loc_args, _) => {
|
||||
walk_call(visitor, f, loc_args);
|
||||
}
|
||||
e => todo!("{:?}", e),
|
||||
}
|
||||
}
|
||||
|
@ -120,6 +124,18 @@ fn walk_when_branch<V: Visitor>(visitor: &mut V, branch: &WhenBranch, expr_var:
|
|||
}
|
||||
}
|
||||
|
||||
fn walk_call<V: Visitor>(
|
||||
visitor: &mut V,
|
||||
f: &(Variable, Loc<Expr>, Variable, Variable),
|
||||
loc_args: &[(Variable, Loc<Expr>)],
|
||||
) {
|
||||
let (fn_var, loc_fn_expr, _lambda_set, _ret) = f;
|
||||
visitor.visit_expr(&loc_fn_expr.value, loc_fn_expr.region, *fn_var);
|
||||
loc_args
|
||||
.iter()
|
||||
.for_each(|(v, e)| visitor.visit_expr(&e.value, e.region, *v));
|
||||
}
|
||||
|
||||
fn walk_pattern<V: Visitor>(_visitor: &mut V, _pat: &Pattern) {
|
||||
todo!()
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue