mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 16:21:11 +00:00
use vectors instead of maps
This commit is contained in:
parent
7b37727175
commit
5840693743
1 changed files with 123 additions and 83 deletions
|
@ -11,7 +11,7 @@ use crate::reference_matrix::ReferenceMatrix;
|
||||||
use crate::reference_matrix::TopologicalSort;
|
use crate::reference_matrix::TopologicalSort;
|
||||||
use crate::scope::create_alias;
|
use crate::scope::create_alias;
|
||||||
use crate::scope::Scope;
|
use crate::scope::Scope;
|
||||||
use roc_collections::{default_hasher, ImEntry, ImMap, ImSet, MutMap, MutSet, SendMap};
|
use roc_collections::{ImEntry, ImMap, ImSet, MutMap, MutSet, SendMap};
|
||||||
use roc_module::ident::Lowercase;
|
use roc_module::ident::Lowercase;
|
||||||
use roc_module::symbol::IdentId;
|
use roc_module::symbol::IdentId;
|
||||||
use roc_module::symbol::ModuleId;
|
use roc_module::symbol::ModuleId;
|
||||||
|
@ -28,7 +28,6 @@ use roc_types::subs::{VarStore, Variable};
|
||||||
use roc_types::types::AliasKind;
|
use roc_types::types::AliasKind;
|
||||||
use roc_types::types::LambdaSet;
|
use roc_types::types::LambdaSet;
|
||||||
use roc_types::types::{Alias, Type};
|
use roc_types::types::{Alias, Type};
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use ven_graph::topological_sort;
|
use ven_graph::topological_sort;
|
||||||
|
|
||||||
|
@ -50,10 +49,12 @@ pub struct Annotation {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CanDefs {
|
pub(crate) struct CanDefs {
|
||||||
pub refs_by_symbol: MutMap<Symbol, (Region, References)>,
|
symbol_to_index: Vec<(IdentId, u32)>,
|
||||||
pub can_defs_by_symbol: MutMap<Symbol, Def>,
|
defs: Vec<Def>,
|
||||||
pub aliases: SendMap<Symbol, Alias>,
|
references: Vec<(References, Region)>,
|
||||||
|
|
||||||
|
aliases: SendMap<Symbol, Alias>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Def that has had patterns and type annnotations canonicalized,
|
/// A Def that has had patterns and type annnotations canonicalized,
|
||||||
|
@ -205,7 +206,7 @@ fn sort_type_defs_before_introduction(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn canonicalize_defs<'a>(
|
pub(crate) fn canonicalize_defs<'a>(
|
||||||
env: &mut Env<'a>,
|
env: &mut Env<'a>,
|
||||||
mut output: Output,
|
mut output: Output,
|
||||||
var_store: &mut VarStore,
|
var_store: &mut VarStore,
|
||||||
|
@ -234,7 +235,6 @@ pub fn canonicalize_defs<'a>(
|
||||||
// so we can diff them while detecting unused defs.
|
// so we can diff them while detecting unused defs.
|
||||||
let mut scope = original_scope.clone();
|
let mut scope = original_scope.clone();
|
||||||
let num_defs = loc_defs.len();
|
let num_defs = loc_defs.len();
|
||||||
let mut refs_by_symbol = MutMap::default();
|
|
||||||
|
|
||||||
let mut type_defs = Vec::with_capacity(num_defs);
|
let mut type_defs = Vec::with_capacity(num_defs);
|
||||||
let mut value_defs = Vec::with_capacity(num_defs);
|
let mut value_defs = Vec::with_capacity(num_defs);
|
||||||
|
@ -489,7 +489,7 @@ pub fn canonicalize_defs<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut symbol_to_id: Vec<(IdentId, u32)> = Vec::with_capacity(pending_value_defs.len());
|
let mut symbol_to_index: Vec<(IdentId, u32)> = Vec::with_capacity(pending_value_defs.len());
|
||||||
|
|
||||||
for (def_index, pending_def) in pending_value_defs.iter().enumerate() {
|
for (def_index, pending_def) in pending_value_defs.iter().enumerate() {
|
||||||
for (s, _) in bindings_from_patterns(std::iter::once(pending_def.loc_pattern())) {
|
for (s, _) in bindings_from_patterns(std::iter::once(pending_def.loc_pattern())) {
|
||||||
|
@ -499,23 +499,22 @@ pub fn canonicalize_defs<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_assert_eq!(env.home, s.module_id());
|
debug_assert_eq!(env.home, s.module_id());
|
||||||
debug_assert!(!symbol_to_id.iter().any(|(id, _)| *id == s.ident_id()));
|
debug_assert!(!symbol_to_index.iter().any(|(id, _)| *id == s.ident_id()));
|
||||||
|
|
||||||
symbol_to_id.push((s.ident_id(), def_index as u32));
|
symbol_to_index.push((s.ident_id(), def_index as u32));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// let mut def_order = DefOrdering::from_symbol_to_id(env.home, symbol_to_id);
|
// let mut def_order = DefOrdering::from_symbol_to_id(env.home, symbol_to_id);
|
||||||
|
|
||||||
let mut can_defs_by_symbol = HashMap::with_capacity_and_hasher(num_defs, default_hasher());
|
|
||||||
|
|
||||||
// env.home.register_debug_idents(&env.ident_ids);
|
// env.home.register_debug_idents(&env.ident_ids);
|
||||||
|
|
||||||
|
let mut defs = Vec::with_capacity(pending_value_defs.len());
|
||||||
|
let mut references = Vec::with_capacity(pending_value_defs.len());
|
||||||
|
|
||||||
for pending_def in pending_value_defs.into_iter() {
|
for pending_def in pending_value_defs.into_iter() {
|
||||||
let region = pending_def.loc_pattern().region;
|
let region = pending_def.loc_pattern().region;
|
||||||
|
|
||||||
let bindings = bindings_from_patterns(std::iter::once(pending_def.loc_pattern()));
|
|
||||||
|
|
||||||
let temp_output = canonicalize_pending_value_def_new(
|
let temp_output = canonicalize_pending_value_def_new(
|
||||||
env,
|
env,
|
||||||
pending_def,
|
pending_def,
|
||||||
|
@ -528,10 +527,8 @@ pub fn canonicalize_defs<'a>(
|
||||||
|
|
||||||
output = temp_output.output;
|
output = temp_output.output;
|
||||||
|
|
||||||
for (symbol, _) in bindings {
|
defs.push(temp_output.def);
|
||||||
can_defs_by_symbol.insert(symbol, temp_output.def.clone());
|
references.push((temp_output.references, region));
|
||||||
refs_by_symbol.insert(symbol, (region, temp_output.references.clone()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine which idents we introduced in the course of this process.
|
// Determine which idents we introduced in the course of this process.
|
||||||
|
@ -555,8 +552,9 @@ pub fn canonicalize_defs<'a>(
|
||||||
// defs need to get moved later.
|
// defs need to get moved later.
|
||||||
(
|
(
|
||||||
CanDefs {
|
CanDefs {
|
||||||
refs_by_symbol,
|
symbol_to_index,
|
||||||
can_defs_by_symbol,
|
defs,
|
||||||
|
references,
|
||||||
// The result needs a thread-safe `SendMap`
|
// The result needs a thread-safe `SendMap`
|
||||||
aliases: aliases.into_iter().collect(),
|
aliases: aliases.into_iter().collect(),
|
||||||
},
|
},
|
||||||
|
@ -723,15 +721,15 @@ struct DefOrdering {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DefOrdering {
|
impl DefOrdering {
|
||||||
fn with_capacity(home: ModuleId, capacity: usize) -> Self {
|
// fn with_capacity(home: ModuleId, capacity: usize) -> Self {
|
||||||
Self {
|
// Self {
|
||||||
home,
|
// home,
|
||||||
symbol_to_id: Vec::with_capacity(capacity),
|
// symbol_to_id: Vec::with_capacity(capacity),
|
||||||
references: ReferenceMatrix::new(capacity),
|
// references: ReferenceMatrix::new(capacity),
|
||||||
direct_references: ReferenceMatrix::new(capacity),
|
// direct_references: ReferenceMatrix::new(capacity),
|
||||||
length: capacity as u32,
|
// length: capacity as u32,
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// fn from_symbol_to_id(home: ModuleId, symbol_to_id: Vec<(IdentId, u32)>) -> Self {
|
// fn from_symbol_to_id(home: ModuleId, symbol_to_id: Vec<(IdentId, u32)>) -> Self {
|
||||||
// let capacity = symbol_to_id.len();
|
// let capacity = symbol_to_id.len();
|
||||||
|
@ -747,37 +745,59 @@ impl DefOrdering {
|
||||||
|
|
||||||
fn from_defs_by_symbol(
|
fn from_defs_by_symbol(
|
||||||
env: &Env,
|
env: &Env,
|
||||||
can_defs_by_symbol: &MutMap<Symbol, Def>,
|
symbol_to_id: Vec<(IdentId, u32)>,
|
||||||
refs_by_symbol: &MutMap<Symbol, (Region, References)>,
|
references: &[(References, Region)],
|
||||||
|
capacity: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut this = Self::with_capacity(env.home, can_defs_by_symbol.len());
|
// because of `Pair a b = someDef` patterns, we can have more symbols than defs
|
||||||
|
debug_assert!(symbol_to_id.len() >= capacity);
|
||||||
|
|
||||||
for (i, symbol) in can_defs_by_symbol.keys().enumerate() {
|
let mut this = Self {
|
||||||
debug_assert_eq!(env.home, symbol.module_id());
|
home: env.home,
|
||||||
|
symbol_to_id,
|
||||||
|
references: ReferenceMatrix::new(capacity),
|
||||||
|
direct_references: ReferenceMatrix::new(capacity),
|
||||||
|
length: capacity as u32,
|
||||||
|
};
|
||||||
|
|
||||||
this.symbol_to_id.push((symbol.ident_id(), i as u32));
|
for (ident_id, def_id) in this.symbol_to_id.iter() {
|
||||||
}
|
let def_id = *def_id;
|
||||||
|
let references = &references[def_id as usize].0;
|
||||||
for (symbol, (_, references)) in refs_by_symbol.iter() {
|
let symbol = Symbol::new(this.home, *ident_id);
|
||||||
let def_id = this.get_id(*symbol).unwrap();
|
|
||||||
|
|
||||||
for referenced in references.value_lookups() {
|
for referenced in references.value_lookups() {
|
||||||
this.register_reference(def_id, *referenced);
|
if let Some(ref_id) = this.get_id(*referenced) {
|
||||||
this.register_direct_reference(def_id, *referenced);
|
this.references
|
||||||
|
.set_row_col(def_id as usize, ref_id as usize, true);
|
||||||
|
|
||||||
|
this.direct_references
|
||||||
|
.set_row_col(def_id as usize, ref_id as usize, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for referenced in references.calls() {
|
for referenced in references.calls() {
|
||||||
this.register_reference(def_id, *referenced);
|
if let Some(ref_id) = this.get_id(*referenced) {
|
||||||
this.register_direct_reference(def_id, *referenced);
|
this.references
|
||||||
|
.set_row_col(def_id as usize, ref_id as usize, true);
|
||||||
|
|
||||||
|
this.direct_references
|
||||||
|
.set_row_col(def_id as usize, ref_id as usize, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(references) = env.closures.get(symbol) {
|
if let Some(references) = env.closures.get(&symbol) {
|
||||||
for referenced in references.value_lookups() {
|
for referenced in references.value_lookups() {
|
||||||
this.register_reference(def_id, *referenced);
|
if let Some(ref_id) = this.get_id(*referenced) {
|
||||||
|
this.references
|
||||||
|
.set_row_col(def_id as usize, ref_id as usize, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for referenced in references.calls() {
|
for referenced in references.calls() {
|
||||||
this.register_reference(def_id, *referenced);
|
if let Some(ref_id) = this.get_id(*referenced) {
|
||||||
|
this.references
|
||||||
|
.set_row_col(def_id as usize, ref_id as usize, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -785,6 +805,46 @@ impl DefOrdering {
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fn from_defs_by_symbol_old(
|
||||||
|
// env: &Env,
|
||||||
|
// can_defs_by_symbol: &MutMap<Symbol, Def>,
|
||||||
|
// refs_by_symbol: &MutMap<Symbol, (Region, References)>,
|
||||||
|
// ) -> Self {
|
||||||
|
// let mut this = Self::with_capacity(env.home, can_defs_by_symbol.len());
|
||||||
|
//
|
||||||
|
// for (i, symbol) in can_defs_by_symbol.keys().enumerate() {
|
||||||
|
// debug_assert_eq!(env.home, symbol.module_id());
|
||||||
|
//
|
||||||
|
// this.symbol_to_id.push((symbol.ident_id(), i as u32));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// for (symbol, (_, references)) in refs_by_symbol.iter() {
|
||||||
|
// let def_id = this.get_id(*symbol).unwrap();
|
||||||
|
//
|
||||||
|
// for referenced in references.value_lookups() {
|
||||||
|
// this.register_reference(def_id, *referenced);
|
||||||
|
// this.register_direct_reference(def_id, *referenced);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// for referenced in references.calls() {
|
||||||
|
// this.register_reference(def_id, *referenced);
|
||||||
|
// this.register_direct_reference(def_id, *referenced);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if let Some(references) = env.closures.get(symbol) {
|
||||||
|
// for referenced in references.value_lookups() {
|
||||||
|
// this.register_reference(def_id, *referenced);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// for referenced in references.calls() {
|
||||||
|
// this.register_reference(def_id, *referenced);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// this
|
||||||
|
// }
|
||||||
|
|
||||||
fn get_id(&self, symbol: Symbol) -> Option<u32> {
|
fn get_id(&self, symbol: Symbol) -> Option<u32> {
|
||||||
if symbol.module_id() != self.home {
|
if symbol.module_id() != self.home {
|
||||||
return None;
|
return None;
|
||||||
|
@ -811,20 +871,6 @@ impl DefOrdering {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_direct_reference(&mut self, id: u32, referenced: Symbol) {
|
|
||||||
if let Some(ref_id) = self.get_id(referenced) {
|
|
||||||
self.direct_references
|
|
||||||
.set_row_col(id as usize, ref_id as usize, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn register_reference(&mut self, id: u32, referenced: Symbol) {
|
|
||||||
if let Some(ref_id) = self.get_id(referenced) {
|
|
||||||
self.references
|
|
||||||
.set_row_col(id as usize, ref_id as usize, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_self_recursive(&self, id: u32) -> bool {
|
fn is_self_recursive(&self, id: u32) -> bool {
|
||||||
debug_assert!(id < self.length);
|
debug_assert!(id < self.length);
|
||||||
|
|
||||||
|
@ -848,20 +894,20 @@ impl DefOrdering {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn sort_can_defs(
|
pub(crate) fn sort_can_defs(
|
||||||
env: &mut Env<'_>,
|
env: &mut Env<'_>,
|
||||||
defs: CanDefs,
|
defs: CanDefs,
|
||||||
mut output: Output,
|
mut output: Output,
|
||||||
) -> (Result<Vec<Declaration>, RuntimeError>, Output) {
|
) -> (Result<Vec<Declaration>, RuntimeError>, Output) {
|
||||||
let def_ids =
|
|
||||||
DefOrdering::from_defs_by_symbol(env, &defs.can_defs_by_symbol, &defs.refs_by_symbol);
|
|
||||||
|
|
||||||
let CanDefs {
|
let CanDefs {
|
||||||
refs_by_symbol,
|
symbol_to_index,
|
||||||
mut can_defs_by_symbol,
|
defs,
|
||||||
|
references,
|
||||||
aliases,
|
aliases,
|
||||||
} = defs;
|
} = defs;
|
||||||
|
|
||||||
|
let def_ids = DefOrdering::from_defs_by_symbol(env, symbol_to_index, &references, defs.len());
|
||||||
|
|
||||||
for (symbol, alias) in aliases.into_iter() {
|
for (symbol, alias) in aliases.into_iter() {
|
||||||
output.aliases.insert(symbol, alias);
|
output.aliases.insert(symbol, alias);
|
||||||
}
|
}
|
||||||
|
@ -874,13 +920,7 @@ pub fn sort_can_defs(
|
||||||
|
|
||||||
// groups are in reversed order
|
// groups are in reversed order
|
||||||
for group in groups.into_iter().rev() {
|
for group in groups.into_iter().rev() {
|
||||||
group_to_declaration(
|
group_to_declaration(&def_ids, &group, &env.closures, &defs, &mut declarations);
|
||||||
&def_ids,
|
|
||||||
&group,
|
|
||||||
&env.closures,
|
|
||||||
&mut can_defs_by_symbol,
|
|
||||||
&mut declarations,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(Ok(declarations), output)
|
(Ok(declarations), output)
|
||||||
|
@ -931,14 +971,14 @@ pub fn sort_can_defs(
|
||||||
|
|
||||||
for def_id in &cycle {
|
for def_id in &cycle {
|
||||||
let symbol = def_ids.get_symbol(*def_id).unwrap();
|
let symbol = def_ids.get_symbol(*def_id).unwrap();
|
||||||
match refs_by_symbol.get(&symbol) {
|
match references.get(*def_id as usize) {
|
||||||
None => unreachable!(
|
None => unreachable!(
|
||||||
r#"Symbol `{:?}` not found in refs_by_symbol! refs_by_symbol was: {:?}"#,
|
r#"Symbol `{:?}` not found in references! references was: {:?}"#,
|
||||||
symbol, refs_by_symbol
|
symbol, references
|
||||||
),
|
),
|
||||||
Some((region, _)) => {
|
Some((_, region)) => {
|
||||||
let expr_region =
|
let expr_region =
|
||||||
can_defs_by_symbol.get(&symbol).unwrap().loc_expr.region;
|
defs.get(*def_id as usize).unwrap().loc_expr.region;
|
||||||
|
|
||||||
let entry = CycleEntry {
|
let entry = CycleEntry {
|
||||||
symbol,
|
symbol,
|
||||||
|
@ -1016,7 +1056,7 @@ pub fn sort_can_defs(
|
||||||
&def_ids,
|
&def_ids,
|
||||||
group,
|
group,
|
||||||
&env.closures,
|
&env.closures,
|
||||||
&mut can_defs_by_symbol,
|
&defs,
|
||||||
&mut declarations,
|
&mut declarations,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1038,7 +1078,7 @@ fn group_to_declaration(
|
||||||
def_ids: &DefOrdering,
|
def_ids: &DefOrdering,
|
||||||
group: &[u32],
|
group: &[u32],
|
||||||
closures: &MutMap<Symbol, References>,
|
closures: &MutMap<Symbol, References>,
|
||||||
can_defs_by_symbol: &mut MutMap<Symbol, Def>,
|
defs: &[Def],
|
||||||
declarations: &mut Vec<Declaration>,
|
declarations: &mut Vec<Declaration>,
|
||||||
) {
|
) {
|
||||||
use Declaration::*;
|
use Declaration::*;
|
||||||
|
@ -1059,7 +1099,7 @@ fn group_to_declaration(
|
||||||
let def_id = cycle[0];
|
let def_id = cycle[0];
|
||||||
let symbol = def_ids.get_symbol(def_id).unwrap();
|
let symbol = def_ids.get_symbol(def_id).unwrap();
|
||||||
|
|
||||||
match can_defs_by_symbol.remove(&symbol) {
|
match defs.get(def_id as usize).cloned() {
|
||||||
Some(mut new_def) => {
|
Some(mut new_def) => {
|
||||||
// there is only one definition in this cycle, so we only have
|
// there is only one definition in this cycle, so we only have
|
||||||
// to check whether it recurses with itself; there is nobody else
|
// to check whether it recurses with itself; there is nobody else
|
||||||
|
@ -1094,7 +1134,7 @@ fn group_to_declaration(
|
||||||
// Topological sort gives us the reverse of the sorting we want!
|
// Topological sort gives us the reverse of the sorting we want!
|
||||||
for def_id in cycle.into_iter().rev() {
|
for def_id in cycle.into_iter().rev() {
|
||||||
let symbol = def_ids.get_symbol(def_id).unwrap();
|
let symbol = def_ids.get_symbol(def_id).unwrap();
|
||||||
match can_defs_by_symbol.remove(&symbol) {
|
match defs.get(def_id as usize).cloned() {
|
||||||
Some(mut new_def) => {
|
Some(mut new_def) => {
|
||||||
// Determine recursivity of closures that are not tail-recursive
|
// Determine recursivity of closures that are not tail-recursive
|
||||||
if let Closure(ClosureData {
|
if let Closure(ClosureData {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue