can::Expr::ParamsVar for lookups with params

This commit is contained in:
Agus Zubiaga 2024-05-09 23:58:05 -03:00
parent 5aebb7b570
commit 1526fc4aee
No known key found for this signature in database
7 changed files with 67 additions and 5 deletions

View file

@ -288,6 +288,15 @@ fn deep_copy_expr_help<C: CopyEnv>(env: &mut C, copied: &mut Vec<Variable>, expr
loc_elems: loc_elems.iter().map(|le| le.map(|e| go_help!(e))).collect(),
},
Var(sym, var) => Var(*sym, sub!(*var)),
ParamsVar {
symbol,
params,
var,
} => ParamsVar {
symbol: *symbol,
params: *params,
var: sub!(*var),
},
&AbilityMember(sym, specialization, specialization_var) => {
AbilityMember(sym, specialization, sub!(specialization_var))
}

View file

@ -206,7 +206,9 @@ fn expr<'a>(c: &Ctx, p: EPrec, f: &'a Arena<'a>, e: &'a Expr) -> DocBuilder<'a,
.append("]")
.group(),
),
Var(sym, _) | AbilityMember(sym, _, _) => pp_sym(c, f, *sym),
Var(sym, _) | ParamsVar { symbol: sym, .. } | AbilityMember(sym, _, _) => {
pp_sym(c, f, *sym)
}
When {
loc_cond, branches, ..
} => maybe_paren!(

View file

@ -17,7 +17,7 @@ use roc_error_macros::internal_error;
use roc_module::called_via::CalledVia;
use roc_module::ident::{ForeignSymbol, Lowercase, TagName};
use roc_module::low_level::LowLevel;
use roc_module::symbol::Symbol;
use roc_module::symbol::{LookedupSymbol, Symbol};
use roc_parse::ast::{self, Defs, PrecedenceConflict, StrLiteral};
use roc_parse::ident::Accessor;
use roc_parse::pattern::PatternType::*;
@ -107,6 +107,12 @@ pub enum Expr {
// Lookups
Var(Symbol, Variable),
/// Like Var, but from a module with params
ParamsVar {
symbol: Symbol,
params: Symbol,
var: Variable,
},
AbilityMember(
/// Actual member name
Symbol,
@ -308,6 +314,11 @@ impl Expr {
Self::SingleQuote(..) => Category::Character,
Self::List { .. } => Category::List,
&Self::Var(sym, _) => Category::Lookup(sym),
&Self::ParamsVar {
symbol,
params: _,
var: _,
} => Category::Lookup(symbol),
&Self::AbilityMember(sym, _, _) => Category::Lookup(sym),
Self::When { .. } => Category::When,
Self::If { .. } => Category::If,
@ -1872,7 +1883,7 @@ fn canonicalize_var_lookup(
var_store.fresh(),
)
} else {
Var(lookup, var_store.fresh())
lookup_to_expr(lookup, var_store.fresh())
}
}
Err(problem) => {
@ -1898,7 +1909,7 @@ fn canonicalize_var_lookup(
var_store.fresh(),
)
} else {
Var(lookup, var_store.fresh())
lookup_to_expr(lookup, var_store.fresh())
}
}
Err(problem) => {
@ -1916,6 +1927,18 @@ fn canonicalize_var_lookup(
(can_expr, output)
}
fn lookup_to_expr(LookedupSymbol { symbol, params }: LookedupSymbol, var: Variable) -> Expr {
if let Some(params) = params {
Expr::ParamsVar {
symbol,
params,
var,
}
} else {
Expr::Var(symbol, var)
}
}
/// Currently uses the heuristic of "only inline if it's a builtin"
pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
use Expr::*;
@ -1934,6 +1957,7 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
| other @ RecordAccessor { .. }
| other @ RecordUpdate { .. }
| other @ Var(..)
| other @ ParamsVar { .. }
| other @ AbilityMember(..)
| other @ RunLowLevel { .. }
| other @ TypedHole { .. }
@ -3100,6 +3124,11 @@ pub(crate) fn get_lookup_symbols(expr: &Expr) -> Vec<ExpectLookup> {
while let Some(expr) = stack.pop() {
match expr {
Expr::Var(symbol, var)
| Expr::ParamsVar {
symbol,
params: _,
var,
}
| Expr::RecordUpdate {
symbol,
record_var: var,

View file

@ -1105,6 +1105,7 @@ fn fix_values_captured_in_closure_expr(
| SingleQuote(..)
| IngestedFile(..)
| Var(..)
| ParamsVar { .. }
| AbilityMember(..)
| EmptyRecord
| TypedHole { .. }

View file

@ -266,6 +266,7 @@ pub fn walk_expr<V: Visitor>(visitor: &mut V, expr: &Expr, var: Variable) {
walk_list(visitor, *elem_var, loc_elems);
}
Expr::Var(..) => { /* terminal */ }
Expr::ParamsVar { .. } => { /* terminal */ }
Expr::AbilityMember(..) => { /* terminal */ }
Expr::If {
cond_var,

View file

@ -575,6 +575,22 @@ pub fn constrain_expr(
constraints.and_constraint([store_expected, lookup_constr])
}
ParamsVar {
symbol,
params,
var,
} => {
// Save the expectation in the variable, then lookup the symbol's type in the environment
let expected_type = *constraints[expected].get_type_ref();
let store_expected = constraints.store(expected_type, *var, file!(), line!());
let lookup_constr = constraints.lookup(*symbol, expected, region);
// todo(agus): check params
// let params_constr = constraints.lookup(*params, expected, region);
constraints.and_constraint([store_expected, lookup_constr])
}
&AbilityMember(symbol, specialization_id, specialization_var) => {
// Save the expectation in the `specialization_var` so we know what to specialize, then
// lookup the member in the environment.
@ -4115,7 +4131,8 @@ fn is_generalizable_expr(mut expr: &Expr) -> bool {
| ZeroArgumentTag { .. }
| Tag { .. }
| AbilityMember(..)
| Var(..) => return false,
| Var(..)
| ParamsVar { .. } => return false,
}
}
}

View file

@ -4422,6 +4422,9 @@ pub fn with_hole<'a>(
specialize_naked_symbol(env, variable, procs, layout_cache, assigned, hole, symbol)
}
ParamsVar { .. } => {
todo!("agus: handle params var")
}
AbilityMember(member, specialization_id, specialization_var) => {
let specialization_symbol = late_resolve_ability_specialization(
env,