Restore uniq::sharing

This commit is contained in:
Richard Feldman 2020-07-04 22:13:04 -04:00
parent 06c05e5e9b
commit 73d920e96f
2 changed files with 69 additions and 73 deletions

View file

@ -1,8 +1,8 @@
use roc_can::expr::Expr; use roc_can::expr::Expr;
use roc_collections::all::{ImMap, ImSet}; use roc_collections::all::{ImMap, ImSet};
use roc_module::ident::Lowercase; use roc_module::ident::Lowercase;
use roc_module::low_level::LowLevel;
use roc_module::symbol::Symbol; use roc_module::symbol::Symbol;
use roc_region::all::Located;
use roc_types::subs::Variable; use roc_types::subs::Variable;
// fake field names for container elements // fake field names for container elements
@ -527,7 +527,8 @@ pub fn annotate_usage(expr: &Expr, usage: &mut VarUsage) {
| Str(_) | Str(_)
| BlockStr(_) | BlockStr(_)
| EmptyRecord | EmptyRecord
| Accessor { .. } => {} | Accessor { .. }
| RunLowLevel { .. } => {}
Var(symbol) => usage.register_unique(*symbol), 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); annotate_usage(&loc_expr.value, usage);
} }
Call(fun, loc_args, _) => { Call(fun, loc_args, _) => {
match fun.1.value { if let Var(symbol) = fun.1.value {
Var(symbol) => {
// call by name // call by name
usage.register_unique(symbol); special_case_builtins(usage, symbol, loc_args);
} else {
for (_, arg) in loc_args {
annotate_usage(&arg.value, usage);
}
}
_ => {
// unknown call // unknown call
annotate_usage(&fun.1.value, usage); 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) => { Closure(_, _, _, _, body) => {
annotate_usage(&body.0.value, usage); 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, usage: &mut VarUsage,
op: LowLevel, symbol: Symbol,
args: &[(Variable, Expr)], loc_args: &[(Variable, Located<Expr>)],
_ret_var: Variable,
) { ) {
use Expr::Var; use Expr::Var;
use LowLevel::*;
use Mark::*; use Mark::*;
use Usage::*; use Usage::*;
match symbol {
Symbol::LIST_GET => {
debug_assert!(loc_args.len() == 2);
match op { let loc_list = &loc_args[0].1;
ListLen | ListGetUnsafe => { let loc_index = &loc_args[1].1;
match &args[0].1 {
Var(list_var) => { if let Var(list_var) = loc_list.value {
usage.register_with( usage.register_with(
*list_var, list_var,
&Access(Container::List, Seen, FieldAccess::list_seen()), &Access(Container::List, Seen, FieldAccess::list_access()),
); );
} else {
annotate_usage(&loc_list.value, usage);
} }
list => { annotate_usage(&loc_index.value, usage);
annotate_usage(list, usage);
}
} }
for (_, arg) in &args[1..] { Symbol::LIST_SET => {
annotate_usage(arg, usage); debug_assert!(loc_args.len() == 3);
}
}
ListSet | ListSetInPlace | ListPush => { let loc_list = &loc_args[0].1;
match &args[0].1 { let loc_index = &loc_args[1].1;
Var(list_var) => { let loc_value = &loc_args[2].1;
if let Var(list_var) = loc_list.value {
usage.register_with( usage.register_with(
*list_var, list_var,
&Update( &Update(
Container::List, Container::List,
ImSet::default(), ImSet::default(),
FieldAccess::list_update(), FieldAccess::list_update(),
), ),
); );
} else {
annotate_usage(&loc_list.value, usage);
} }
list => { annotate_usage(&loc_index.value, usage);
annotate_usage(list, 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 for (_, arg) in loc_args {
| NumNeg | NumDivUnchecked | NumRemUnchecked | NumSqrtUnchecked | NumRound | NumSin annotate_usage(&arg.value, usage);
| NumCos | Eq | NotEq | And | Or | Not | NumToFloat | ListRepeat => {
for (_, arg) in args {
annotate_usage(&arg, usage);
} }
} }
} }

View file

@ -15,12 +15,9 @@ mod helpers;
#[cfg(test)] #[cfg(test)]
mod test_usage_analysis { mod test_usage_analysis {
use crate::helpers::{can_expr, test_home, CanExprOut}; 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_collections::all::{ImMap, ImSet};
use roc_module::ident::Lowercase; use roc_module::ident::Lowercase;
use roc_module::symbol::{Interns, Symbol}; use roc_module::symbol::{Interns, Symbol};
use roc_types::subs::VarStore;
use roc_uniq::sharing::{self, Container, FieldAccess, Mark, Usage, VarUsage}; use roc_uniq::sharing::{self, Container, FieldAccess, Mark, Usage, VarUsage};
use std::collections::HashMap; use std::collections::HashMap;
@ -189,13 +186,9 @@ mod test_usage_analysis {
loc_expr, interns, .. loc_expr, interns, ..
} = can_expr(src); } = 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; use roc_uniq::sharing::annotate_usage;
let mut usage = VarUsage::default(); let mut usage = VarUsage::default();
annotate_usage(&expr, &mut usage); annotate_usage(&loc_expr.value, &mut usage);
assert_eq!(usage, get_expected(interns)) assert_eq!(usage, get_expected(interns))
} }