mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 21:39:07 +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"),
|
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
|
// The struct indexing generated by the current context
|
||||||
let mut current_struct_indexing = Vec::with_capacity_in(sorted_fields.len(), env.arena);
|
let mut current_struct_indexing = Vec::with_capacity_in(sorted_fields.len(), env.arena);
|
||||||
// The symbols that are used to create the new struct
|
// The symbols that are used to create the new struct
|
||||||
|
@ -4958,10 +4960,14 @@ pub fn with_hole<'a>(
|
||||||
Ok(_field_layout) => {
|
Ok(_field_layout) => {
|
||||||
current_struct_indexing.push(record_index);
|
current_struct_indexing.push(record_index);
|
||||||
|
|
||||||
|
// 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();
|
let original_struct_symbol = env.unique_symbol();
|
||||||
if let Some(field) = updates.get(label) {
|
|
||||||
env.struct_indexing
|
env.struct_indexing
|
||||||
.insert(record_index, original_struct_symbol);
|
.insert(record_index, original_struct_symbol);
|
||||||
|
}
|
||||||
|
if let Some(field) = updates.get(label) {
|
||||||
let new_struct_symbol = possible_reuse_symbol_or_specialize(
|
let new_struct_symbol = possible_reuse_symbol_or_specialize(
|
||||||
env,
|
env,
|
||||||
procs,
|
procs,
|
||||||
|
@ -4972,8 +4978,6 @@ pub fn with_hole<'a>(
|
||||||
new_struct_symbols.push(new_struct_symbol);
|
new_struct_symbols.push(new_struct_symbol);
|
||||||
fields.push(UpdateExisting(field));
|
fields.push(UpdateExisting(field));
|
||||||
} else {
|
} else {
|
||||||
env.struct_indexing
|
|
||||||
.insert(record_index, original_struct_symbol);
|
|
||||||
new_struct_symbols
|
new_struct_symbols
|
||||||
.push(*env.struct_indexing.get(record_index).unwrap());
|
.push(*env.struct_indexing.get(record_index).unwrap());
|
||||||
fields.push(CopyExisting);
|
fields.push(CopyExisting);
|
||||||
|
@ -4995,7 +4999,7 @@ pub fn with_hole<'a>(
|
||||||
_ => arena.alloc([record_layout]),
|
_ => 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
|
// TODO we can probably special-case this more, skipping the generation of
|
||||||
// UpdateExisting
|
// UpdateExisting
|
||||||
let mut stmt = hole.clone();
|
let mut stmt = hole.clone();
|
||||||
|
@ -5061,9 +5065,7 @@ pub fn with_hole<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
for record_index in current_struct_indexing.into_iter().rev() {
|
for record_index in current_struct_indexing.into_iter().rev() {
|
||||||
let (symbol, usage) = env.struct_indexing.pop(&record_index).unwrap();
|
if let Some(symbol) = env.struct_indexing.get_used(&record_index) {
|
||||||
match usage {
|
|
||||||
Usage::Used => {
|
|
||||||
let layout = field_layouts[record_index.1 as usize];
|
let layout = field_layouts[record_index.1 as usize];
|
||||||
let access_expr = Expr::StructAtIndex {
|
let access_expr = Expr::StructAtIndex {
|
||||||
structure: specialized_structure_sym,
|
structure: specialized_structure_sym,
|
||||||
|
@ -5071,9 +5073,7 @@ pub fn with_hole<'a>(
|
||||||
field_layouts,
|
field_layouts,
|
||||||
};
|
};
|
||||||
stmt = Stmt::Let(symbol, access_expr, layout, arena.alloc(stmt));
|
stmt = Stmt::Let(symbol, access_expr, layout, arena.alloc(stmt));
|
||||||
}
|
};
|
||||||
Usage::Unused => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if structure_needs_specialization {
|
if structure_needs_specialization {
|
||||||
|
@ -10101,7 +10101,10 @@ where
|
||||||
Some(value)
|
Some(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop(&mut self, key: &K) -> Option<(V, Usage)> {
|
fn get_used(&mut self, key: &K) -> Option<V> {
|
||||||
self.map.remove(key)
|
self.map.remove(key).and_then(|(value, usage)| match usage {
|
||||||
|
Usage::Used => Some(value),
|
||||||
|
Usage::Unused => None,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
procedure Test.1 (Test.2):
|
procedure Test.1 (Test.2):
|
||||||
dec Test.2;
|
dec Test.2;
|
||||||
let Test.8 : Str = "ux";
|
let Test.7 : Str = "ux";
|
||||||
let Test.9 : Str = "uy";
|
let Test.8 : Str = "uy";
|
||||||
let Test.7 : {Str, Str} = Struct {Test.8, Test.9};
|
let Test.6 : {Str, Str} = Struct {Test.7, Test.8};
|
||||||
ret Test.7;
|
ret Test.6;
|
||||||
|
|
||||||
procedure Test.0 ():
|
procedure Test.0 ():
|
||||||
let Test.11 : Str = "x";
|
let Test.10 : Str = "x";
|
||||||
let Test.12 : Str = "y";
|
let Test.11 : Str = "y";
|
||||||
let Test.10 : {Str, Str} = Struct {Test.11, Test.12};
|
let Test.9 : {Str, Str} = Struct {Test.10, Test.11};
|
||||||
let Test.3 : {Str, Str} = CallByName Test.1 Test.10;
|
let Test.3 : {Str, Str} = CallByName Test.1 Test.9;
|
||||||
ret Test.3;
|
ret Test.3;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue