mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 23:31:12 +00:00
Restore uniq::sharing
This commit is contained in:
parent
06c05e5e9b
commit
73d920e96f
2 changed files with 69 additions and 73 deletions
|
@ -1,8 +1,8 @@
|
|||
use roc_can::expr::Expr;
|
||||
use roc_collections::all::{ImMap, ImSet};
|
||||
use roc_module::ident::Lowercase;
|
||||
use roc_module::low_level::LowLevel;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_region::all::Located;
|
||||
use roc_types::subs::Variable;
|
||||
|
||||
// fake field names for container elements
|
||||
|
@ -527,7 +527,8 @@ pub fn annotate_usage(expr: &Expr, usage: &mut VarUsage) {
|
|||
| Str(_)
|
||||
| BlockStr(_)
|
||||
| EmptyRecord
|
||||
| Accessor { .. } => {}
|
||||
| Accessor { .. }
|
||||
| RunLowLevel { .. } => {}
|
||||
|
||||
Var(symbol) => usage.register_unique(*symbol),
|
||||
|
||||
|
@ -618,16 +619,10 @@ pub fn annotate_usage(expr: &Expr, usage: &mut VarUsage) {
|
|||
annotate_usage(&loc_expr.value, usage);
|
||||
}
|
||||
Call(fun, loc_args, _) => {
|
||||
match fun.1.value {
|
||||
Var(symbol) => {
|
||||
if let Var(symbol) = fun.1.value {
|
||||
// call by name
|
||||
usage.register_unique(symbol);
|
||||
|
||||
for (_, arg) in loc_args {
|
||||
annotate_usage(&arg.value, usage);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
special_case_builtins(usage, symbol, loc_args);
|
||||
} else {
|
||||
// unknown call
|
||||
annotate_usage(&fun.1.value, usage);
|
||||
|
||||
|
@ -636,10 +631,6 @@ pub fn annotate_usage(expr: &Expr, usage: &mut VarUsage) {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
RunLowLevel { op, args, ret_var } => {
|
||||
annotate_low_level_usage(usage, *op, args, *ret_var);
|
||||
}
|
||||
Closure(_, _, _, _, body) => {
|
||||
annotate_usage(&body.0.value, usage);
|
||||
}
|
||||
|
@ -703,63 +694,75 @@ fn get_access_chain<'a>(expr: &'a Expr, chain: &mut Vec<Lowercase>) -> Option<&'
|
|||
}
|
||||
}
|
||||
|
||||
fn annotate_low_level_usage(
|
||||
fn special_case_builtins(
|
||||
usage: &mut VarUsage,
|
||||
op: LowLevel,
|
||||
args: &[(Variable, Expr)],
|
||||
_ret_var: Variable,
|
||||
symbol: Symbol,
|
||||
loc_args: &[(Variable, Located<Expr>)],
|
||||
) {
|
||||
use Expr::Var;
|
||||
use LowLevel::*;
|
||||
use Mark::*;
|
||||
use Usage::*;
|
||||
match symbol {
|
||||
Symbol::LIST_GET => {
|
||||
debug_assert!(loc_args.len() == 2);
|
||||
|
||||
match op {
|
||||
ListLen | ListGetUnsafe => {
|
||||
match &args[0].1 {
|
||||
Var(list_var) => {
|
||||
let loc_list = &loc_args[0].1;
|
||||
let loc_index = &loc_args[1].1;
|
||||
|
||||
if let Var(list_var) = loc_list.value {
|
||||
usage.register_with(
|
||||
*list_var,
|
||||
&Access(Container::List, Seen, FieldAccess::list_seen()),
|
||||
list_var,
|
||||
&Access(Container::List, Seen, FieldAccess::list_access()),
|
||||
);
|
||||
} else {
|
||||
annotate_usage(&loc_list.value, usage);
|
||||
}
|
||||
list => {
|
||||
annotate_usage(list, usage);
|
||||
}
|
||||
annotate_usage(&loc_index.value, usage);
|
||||
}
|
||||
|
||||
for (_, arg) in &args[1..] {
|
||||
annotate_usage(arg, usage);
|
||||
}
|
||||
}
|
||||
Symbol::LIST_SET => {
|
||||
debug_assert!(loc_args.len() == 3);
|
||||
|
||||
ListSet | ListSetInPlace | ListPush => {
|
||||
match &args[0].1 {
|
||||
Var(list_var) => {
|
||||
let loc_list = &loc_args[0].1;
|
||||
let loc_index = &loc_args[1].1;
|
||||
let loc_value = &loc_args[2].1;
|
||||
|
||||
if let Var(list_var) = loc_list.value {
|
||||
usage.register_with(
|
||||
*list_var,
|
||||
list_var,
|
||||
&Update(
|
||||
Container::List,
|
||||
ImSet::default(),
|
||||
FieldAccess::list_update(),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
annotate_usage(&loc_list.value, usage);
|
||||
}
|
||||
list => {
|
||||
annotate_usage(list, usage);
|
||||
annotate_usage(&loc_index.value, usage);
|
||||
annotate_usage(&loc_value.value, usage);
|
||||
}
|
||||
|
||||
Symbol::LIST_IS_EMPTY | Symbol::LIST_LEN => {
|
||||
debug_assert!(loc_args.len() == 1);
|
||||
|
||||
let loc_list = &loc_args[0].1;
|
||||
|
||||
if let Var(list_var) = loc_list.value {
|
||||
usage.register_with(
|
||||
list_var,
|
||||
&Access(Container::List, Seen, FieldAccess::list_seen()),
|
||||
);
|
||||
} else {
|
||||
annotate_usage(&loc_list.value, usage);
|
||||
}
|
||||
}
|
||||
|
||||
for (_, arg) in &args[1..] {
|
||||
annotate_usage(arg, usage);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
usage.register_unique(symbol);
|
||||
|
||||
ListSingle | NumAdd | NumSub | NumMul | NumGt | NumGte | NumLt | NumLte | NumAbs
|
||||
| NumNeg | NumDivUnchecked | NumRemUnchecked | NumSqrtUnchecked | NumRound | NumSin
|
||||
| NumCos | Eq | NotEq | And | Or | Not | NumToFloat | ListRepeat => {
|
||||
for (_, arg) in args {
|
||||
annotate_usage(&arg, usage);
|
||||
for (_, arg) in loc_args {
|
||||
annotate_usage(&arg.value, usage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,12 +15,9 @@ mod helpers;
|
|||
#[cfg(test)]
|
||||
mod test_usage_analysis {
|
||||
use crate::helpers::{can_expr, test_home, CanExprOut};
|
||||
use roc_can::expr::inline_calls;
|
||||
use roc_can::scope::Scope;
|
||||
use roc_collections::all::{ImMap, ImSet};
|
||||
use roc_module::ident::Lowercase;
|
||||
use roc_module::symbol::{Interns, Symbol};
|
||||
use roc_types::subs::VarStore;
|
||||
use roc_uniq::sharing::{self, Container, FieldAccess, Mark, Usage, VarUsage};
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
@ -189,13 +186,9 @@ mod test_usage_analysis {
|
|||
loc_expr, interns, ..
|
||||
} = can_expr(src);
|
||||
|
||||
let scope = &mut Scope::new(test_home());
|
||||
let var_store = &mut VarStore::default();
|
||||
let expr = inline_calls(var_store, scope, loc_expr.value);
|
||||
|
||||
use roc_uniq::sharing::annotate_usage;
|
||||
let mut usage = VarUsage::default();
|
||||
annotate_usage(&expr, &mut usage);
|
||||
annotate_usage(&loc_expr.value, &mut usage);
|
||||
|
||||
assert_eq!(usage, get_expected(interns))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue