mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 07:41:12 +00:00
Merge pull request #990 from rtfeldman/fuse-rc-struct
Fuse rc in structs/closures
This commit is contained in:
commit
065b6ac2e3
5 changed files with 87 additions and 23 deletions
|
@ -157,6 +157,16 @@ impl<'a, 'i> Env<'a, 'i> {
|
|||
}
|
||||
}
|
||||
|
||||
fn insert_struct_info(&mut self, symbol: Symbol, fields: &'a [Layout<'a>]) {
|
||||
self.constructor_map.insert(symbol, 0);
|
||||
self.layout_map.insert(symbol, Layout::Struct(fields));
|
||||
}
|
||||
|
||||
fn remove_struct_info(&mut self, symbol: Symbol) {
|
||||
self.constructor_map.remove(&symbol);
|
||||
self.layout_map.remove(&symbol);
|
||||
}
|
||||
|
||||
pub fn unique_symbol(&mut self) -> Symbol {
|
||||
let ident_id = self.ident_ids.gen_unique();
|
||||
|
||||
|
@ -213,6 +223,10 @@ fn layout_for_constructor<'a>(
|
|||
}
|
||||
}
|
||||
}
|
||||
Struct(fields) => {
|
||||
debug_assert_eq!(constructor, 0);
|
||||
HasFields(fields)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
@ -322,7 +336,39 @@ enum ConstructorLayout<T> {
|
|||
Unknown,
|
||||
}
|
||||
|
||||
pub fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a Stmt<'a> {
|
||||
pub fn expand_and_cancel_proc<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
stmt: &'a Stmt<'a>,
|
||||
arguments: &'a [(Layout<'a>, Symbol)],
|
||||
) -> &'a Stmt<'a> {
|
||||
let mut introduced = Vec::new_in(env.arena);
|
||||
|
||||
for (layout, symbol) in arguments {
|
||||
match layout {
|
||||
Layout::Struct(fields) => {
|
||||
env.insert_struct_info(*symbol, fields);
|
||||
|
||||
introduced.push(*symbol);
|
||||
}
|
||||
Layout::Closure(_, closure_layout, _) => {
|
||||
if let Layout::Struct(fields) = closure_layout.layout {
|
||||
env.insert_struct_info(*symbol, fields);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
let result = expand_and_cancel(env, stmt);
|
||||
|
||||
for symbol in introduced {
|
||||
env.remove_struct_info(symbol);
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a Stmt<'a> {
|
||||
use Stmt::*;
|
||||
|
||||
let mut deferred_default = Deferred {
|
||||
|
@ -351,7 +397,7 @@ pub fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a S
|
|||
// prevent long chains of `Let`s from blowing the stack
|
||||
let mut literal_stack = Vec::new_in(env.arena);
|
||||
|
||||
while !matches!(&expr, Expr::AccessAtIndex { .. } ) {
|
||||
while !matches!(&expr, Expr::AccessAtIndex { .. } | Expr::Struct(_)) {
|
||||
if let Stmt::Let(symbol1, expr1, layout1, cont1) = cont {
|
||||
literal_stack.push((symbol, expr.clone(), layout.clone()));
|
||||
|
||||
|
@ -366,10 +412,10 @@ pub fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a S
|
|||
|
||||
let new_cont;
|
||||
|
||||
if let Expr::AccessAtIndex {
|
||||
match &expr {
|
||||
Expr::AccessAtIndex {
|
||||
structure, index, ..
|
||||
} = &expr
|
||||
{
|
||||
} => {
|
||||
let entry = env
|
||||
.alias_map
|
||||
.entry(*structure)
|
||||
|
@ -383,9 +429,22 @@ pub fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a S
|
|||
env.alias_map
|
||||
.get_mut(structure)
|
||||
.and_then(|map| map.remove(index));
|
||||
}
|
||||
Expr::Struct(_) => {
|
||||
if let Layout::Struct(fields) = layout {
|
||||
env.insert_struct_info(symbol, fields);
|
||||
|
||||
new_cont = expand_and_cancel(env, cont);
|
||||
|
||||
env.remove_struct_info(symbol);
|
||||
} else {
|
||||
new_cont = expand_and_cancel(env, cont);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
new_cont = expand_and_cancel(env, cont);
|
||||
}
|
||||
}
|
||||
|
||||
let stmt = Let(symbol, expr.clone(), layout.clone(), new_cont);
|
||||
let mut stmt = &*env.arena.alloc(stmt);
|
||||
|
|
|
@ -183,7 +183,11 @@ impl<'a> Proc<'a> {
|
|||
};
|
||||
|
||||
for (_, proc) in procs.iter_mut() {
|
||||
let b = expand_rc::expand_and_cancel(&mut env, arena.alloc(proc.body.clone()));
|
||||
let b = expand_rc::expand_and_cancel_proc(
|
||||
&mut env,
|
||||
arena.alloc(proc.body.clone()),
|
||||
proc.args,
|
||||
);
|
||||
proc.body = b.clone();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,7 +70,9 @@ pub struct ClosureLayout<'a> {
|
|||
/// the vec is likely to be small, so linear search is fine
|
||||
captured: &'a [(TagName, &'a [Layout<'a>])],
|
||||
|
||||
layout: &'a Layout<'a>,
|
||||
/// use with care; there is some stuff happening here re. unwrapping
|
||||
/// one-element records that might cause issues
|
||||
pub layout: &'a Layout<'a>,
|
||||
}
|
||||
|
||||
impl<'a> ClosureLayout<'a> {
|
||||
|
|
|
@ -949,8 +949,7 @@ mod test_mono {
|
|||
let Test.5 = 3.14f64;
|
||||
let Test.3 = Struct {Test.4, Test.5};
|
||||
let Test.1 = Index 0 Test.3;
|
||||
inc Test.1;
|
||||
dec Test.3;
|
||||
decref Test.3;
|
||||
ret Test.1;
|
||||
"#
|
||||
),
|
||||
|
|
|
@ -4697,7 +4697,7 @@ mod test_reporting {
|
|||
|
||||
I was expecting to see a private tag name.
|
||||
|
||||
Hint: Private tag names start with a `@` symbol followed by an
|
||||
Hint: Private tag names start with an `@` symbol followed by an
|
||||
uppercase letter, like @UID or @SecretKey.
|
||||
"#
|
||||
),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue