mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
For single update
This commit is contained in:
parent
452bafc616
commit
c6e7d56fb6
2 changed files with 31 additions and 28 deletions
|
@ -4939,6 +4939,8 @@ pub fn with_hole<'a>(
|
|||
Err(_) => return runtime_error(env, "Can't update record with improper layout"),
|
||||
};
|
||||
|
||||
let single_struct_field = sorted_fields.len() == 1;
|
||||
|
||||
// The struct indexing generated by the current context
|
||||
let mut current_struct_indexing = Vec::with_capacity_in(sorted_fields.len(), env.arena);
|
||||
// The symbols that are used to create the new struct
|
||||
|
@ -4958,10 +4960,14 @@ pub fn with_hole<'a>(
|
|||
Ok(_field_layout) => {
|
||||
current_struct_indexing.push(record_index);
|
||||
|
||||
let original_struct_symbol = env.unique_symbol();
|
||||
if let Some(field) = updates.get(label) {
|
||||
// The struct with a single field is optimized in such a way that replacing later indexing will cause an incorrect IR.
|
||||
// Thus, only insert these struct_indices if there is more than one field in the struct.
|
||||
if !single_struct_field {
|
||||
let original_struct_symbol = env.unique_symbol();
|
||||
env.struct_indexing
|
||||
.insert(record_index, original_struct_symbol);
|
||||
}
|
||||
if let Some(field) = updates.get(label) {
|
||||
let new_struct_symbol = possible_reuse_symbol_or_specialize(
|
||||
env,
|
||||
procs,
|
||||
|
@ -4972,8 +4978,6 @@ pub fn with_hole<'a>(
|
|||
new_struct_symbols.push(new_struct_symbol);
|
||||
fields.push(UpdateExisting(field));
|
||||
} else {
|
||||
env.struct_indexing
|
||||
.insert(record_index, original_struct_symbol);
|
||||
new_struct_symbols
|
||||
.push(*env.struct_indexing.get(record_index).unwrap());
|
||||
fields.push(CopyExisting);
|
||||
|
@ -4995,7 +4999,7 @@ pub fn with_hole<'a>(
|
|||
_ => arena.alloc([record_layout]),
|
||||
};
|
||||
|
||||
if new_struct_symbols.len() == 1 {
|
||||
if single_struct_field {
|
||||
// TODO we can probably special-case this more, skipping the generation of
|
||||
// UpdateExisting
|
||||
let mut stmt = hole.clone();
|
||||
|
@ -5061,19 +5065,15 @@ pub fn with_hole<'a>(
|
|||
};
|
||||
|
||||
for record_index in current_struct_indexing.into_iter().rev() {
|
||||
let (symbol, usage) = env.struct_indexing.pop(&record_index).unwrap();
|
||||
match usage {
|
||||
Usage::Used => {
|
||||
let layout = field_layouts[record_index.1 as usize];
|
||||
let access_expr = Expr::StructAtIndex {
|
||||
structure: specialized_structure_sym,
|
||||
index: record_index.1,
|
||||
field_layouts,
|
||||
};
|
||||
stmt = Stmt::Let(symbol, access_expr, layout, arena.alloc(stmt));
|
||||
}
|
||||
Usage::Unused => {}
|
||||
}
|
||||
if let Some(symbol) = env.struct_indexing.get_used(&record_index) {
|
||||
let layout = field_layouts[record_index.1 as usize];
|
||||
let access_expr = Expr::StructAtIndex {
|
||||
structure: specialized_structure_sym,
|
||||
index: record_index.1,
|
||||
field_layouts,
|
||||
};
|
||||
stmt = Stmt::Let(symbol, access_expr, layout, arena.alloc(stmt));
|
||||
};
|
||||
}
|
||||
|
||||
if structure_needs_specialization {
|
||||
|
@ -10101,7 +10101,10 @@ where
|
|||
Some(value)
|
||||
}
|
||||
|
||||
fn pop(&mut self, key: &K) -> Option<(V, Usage)> {
|
||||
self.map.remove(key)
|
||||
fn get_used(&mut self, key: &K) -> Option<V> {
|
||||
self.map.remove(key).and_then(|(value, usage)| match usage {
|
||||
Usage::Used => Some(value),
|
||||
Usage::Unused => None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue