mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
cleanup after review
This commit is contained in:
parent
da9482b7fa
commit
a50f013fce
1 changed files with 83 additions and 112 deletions
|
@ -152,127 +152,98 @@ fn specialize_drops_stmt<'a, 'i>(
|
||||||
|
|
||||||
let mut stmt = stmt;
|
let mut stmt = stmt;
|
||||||
|
|
||||||
let final_continuation = loop {
|
while let Stmt::Let(binding, expr, layout, continuation) = stmt {
|
||||||
match stmt {
|
environment.add_symbol_layout(*binding, *layout);
|
||||||
Stmt::Let(binding, expr, layout, continuation) => {
|
|
||||||
environment.add_symbol_layout(*binding, *layout);
|
|
||||||
|
|
||||||
// update the environment based on the expr
|
// update the environment based on the expr
|
||||||
match expr {
|
match expr {
|
||||||
Call(_) => {
|
Call(_) => {
|
||||||
// Expr::Call is tricky and we are lazy and handle it elsewhere. it
|
// Expr::Call is tricky and we are lazy and handle it elsewhere. it
|
||||||
// ends a chain of eligible Let statements.
|
// ends a chain of eligible Let statements.
|
||||||
break stmt;
|
break;
|
||||||
}
|
}
|
||||||
Literal(crate::ir::Literal::Int(i)) => {
|
Literal(crate::ir::Literal::Int(i)) => {
|
||||||
environment
|
environment
|
||||||
.symbol_index
|
.symbol_index
|
||||||
.insert(*binding, i128::from_ne_bytes(*i) as u64);
|
.insert(*binding, i128::from_ne_bytes(*i) as u64);
|
||||||
}
|
}
|
||||||
Literal(_) => { /* do nothing */ }
|
Literal(_) => { /* do nothing */ }
|
||||||
Tag {
|
Tag {
|
||||||
tag_id,
|
tag_id,
|
||||||
arguments: children,
|
arguments: children,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
environment.symbol_tag.insert(*binding, *tag_id);
|
environment.symbol_tag.insert(*binding, *tag_id);
|
||||||
|
|
||||||
for (index, child) in children.iter().enumerate() {
|
for (index, child) in children.iter().enumerate() {
|
||||||
environment.add_union_child(
|
environment.add_union_child(*binding, *child, *tag_id, index as u64);
|
||||||
*binding,
|
|
||||||
*child,
|
|
||||||
*tag_id,
|
|
||||||
index as u64,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Struct(children) => {
|
|
||||||
for (index, child) in children.iter().enumerate() {
|
|
||||||
environment.add_struct_child(*binding, *child, index as u64);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
StructAtIndex {
|
|
||||||
index, structure, ..
|
|
||||||
} => {
|
|
||||||
environment.add_struct_child(*structure, *binding, *index);
|
|
||||||
// alloc_let_with_continuation!(environment)
|
|
||||||
|
|
||||||
// TODO do we need to remove the indexed value to prevent it from being dropped sooner?
|
|
||||||
// It will only be dropped sooner if the reference count is 1. Which can only happen if there is no increment before.
|
|
||||||
// So we should be fine.
|
|
||||||
}
|
|
||||||
UnionAtIndex {
|
|
||||||
structure,
|
|
||||||
tag_id,
|
|
||||||
index,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
// TODO perhaps we need the union_layout later as well? if so, create a new function/map to store it.
|
|
||||||
environment.add_union_child(*structure, *binding, *tag_id, *index);
|
|
||||||
// Generated code might know the tag of the union without switching on it.
|
|
||||||
// So if we UnionAtIndex, we must know the tag and we can use it to specialize the drop.
|
|
||||||
environment.symbol_tag.insert(*structure, *tag_id);
|
|
||||||
}
|
|
||||||
UnionFieldPtrAtIndex {
|
|
||||||
structure, tag_id, ..
|
|
||||||
} => {
|
|
||||||
// Generated code might know the tag of the union without switching on it.
|
|
||||||
// So if we UnionFieldPtrAtIndex, we must know the tag and we can use it to specialize the drop.
|
|
||||||
environment.symbol_tag.insert(*structure, *tag_id);
|
|
||||||
}
|
|
||||||
Array {
|
|
||||||
elems: children, ..
|
|
||||||
} => {
|
|
||||||
let it =
|
|
||||||
children.iter().enumerate().filter_map(|(index, child)| {
|
|
||||||
match child {
|
|
||||||
ListLiteralElement::Literal(_) => None,
|
|
||||||
ListLiteralElement::Symbol(s) => Some((index, s)),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
for (index, child) in it {
|
|
||||||
environment.add_list_child(*binding, *child, index as u64);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reset { .. } | Expr::ResetRef { .. } => { /* do nothing */ }
|
|
||||||
RuntimeErrorFunction(_)
|
|
||||||
| GetTagId { .. }
|
|
||||||
| EmptyArray
|
|
||||||
| NullPointer => { /* do nothing */ }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// now store the let binding for later
|
|
||||||
stack.push((*binding, expr.clone(), *layout));
|
|
||||||
|
|
||||||
// and "recurse" down the statement chain
|
|
||||||
stmt = continuation;
|
|
||||||
}
|
}
|
||||||
_ => {
|
Struct(children) => {
|
||||||
// the chain of eligeble `Let`s stops at any non-let statement
|
for (index, child) in children.iter().enumerate() {
|
||||||
break stmt;
|
environment.add_struct_child(*binding, *child, index as u64);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
StructAtIndex {
|
||||||
};
|
index, structure, ..
|
||||||
|
} => {
|
||||||
|
environment.add_struct_child(*structure, *binding, *index);
|
||||||
|
|
||||||
let mut final_continuation = specialize_drops_stmt(
|
// TODO do we need to remove the indexed value to prevent it from being dropped sooner?
|
||||||
arena,
|
// It will only be dropped sooner if the reference count is 1. Which can only happen if there is no increment before.
|
||||||
layout_interner,
|
// So we should be fine.
|
||||||
ident_ids,
|
}
|
||||||
environment,
|
UnionAtIndex {
|
||||||
final_continuation,
|
structure,
|
||||||
);
|
tag_id,
|
||||||
|
index,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
// TODO perhaps we need the union_layout later as well? if so, create a new function/map to store it.
|
||||||
|
environment.add_union_child(*structure, *binding, *tag_id, *index);
|
||||||
|
// Generated code might know the tag of the union without switching on it.
|
||||||
|
// So if we UnionAtIndex, we must know the tag and we can use it to specialize the drop.
|
||||||
|
environment.symbol_tag.insert(*structure, *tag_id);
|
||||||
|
}
|
||||||
|
UnionFieldPtrAtIndex {
|
||||||
|
structure, tag_id, ..
|
||||||
|
} => {
|
||||||
|
// Generated code might know the tag of the union without switching on it.
|
||||||
|
// So if we UnionFieldPtrAtIndex, we must know the tag and we can use it to specialize the drop.
|
||||||
|
environment.symbol_tag.insert(*structure, *tag_id);
|
||||||
|
}
|
||||||
|
Array {
|
||||||
|
elems: children, ..
|
||||||
|
} => {
|
||||||
|
let it =
|
||||||
|
children
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(|(index, child)| match child {
|
||||||
|
ListLiteralElement::Literal(_) => None,
|
||||||
|
ListLiteralElement::Symbol(s) => Some((index, s)),
|
||||||
|
});
|
||||||
|
|
||||||
for (binding, expr, layout) in stack.into_iter().rev() {
|
for (index, child) in it {
|
||||||
final_continuation = arena.alloc(Stmt::Let(
|
environment.add_list_child(*binding, *child, index as u64);
|
||||||
binding,
|
}
|
||||||
expr,
|
}
|
||||||
layout,
|
Reset { .. } | Expr::ResetRef { .. } => { /* do nothing */ }
|
||||||
arena.alloc(final_continuation),
|
RuntimeErrorFunction(_) | GetTagId { .. } | EmptyArray | NullPointer => { /* do nothing */
|
||||||
));
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now store the let binding for later
|
||||||
|
stack.push((*binding, expr.clone(), *layout));
|
||||||
|
|
||||||
|
// and "recurse" down the statement chain
|
||||||
|
stmt = continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
final_continuation
|
stack.into_iter().rev().fold(
|
||||||
|
specialize_drops_stmt(arena, layout_interner, ident_ids, environment, stmt),
|
||||||
|
|acc, (binding, expr, layout)| arena.alloc(Stmt::Let(binding, expr, layout, acc)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Stmt::Switch {
|
Stmt::Switch {
|
||||||
cond_symbol,
|
cond_symbol,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue