refactor Path -> Expr conversion

This commit is contained in:
Folkert 2020-11-13 17:04:22 +01:00
parent 11ea52731c
commit 0c86d09ccf

View file

@ -935,80 +935,105 @@ pub fn optimize_when<'a>(
) )
} }
fn path_to_expr_help<'a>( #[derive(Debug)]
env: &mut Env<'a, '_>, struct PathInstruction {
mut symbol: Symbol, index: u64,
mut path: &Path, tag_id: u8,
mut layout: Layout<'a>, }
) -> (Symbol, StoresVec<'a>, Layout<'a>) {
let mut stores = bumpalo::collections::Vec::new_in(env.arena); fn reverse_path(mut path: &Path) -> Vec<PathInstruction> {
let mut result = Vec::new();
loop { loop {
match path { match path {
Path::Unbox(unboxed) => { Path::Unbox(nested) => {
path = unboxed; path = nested;
} }
Path::Empty => break, Path::Empty => break,
Path::Index { Path::Index {
index, index,
tag_id, tag_id,
path: nested, path: nested,
} => match Wrapped::opt_from_layout(&layout) { } => {
None => { result.push(PathInstruction {
// this MUST be an index into a single-element (hence unwrapped) record index: *index,
tag_id: *tag_id,
});
path = nested;
}
}
}
debug_assert_eq!(*index, 0); result.reverse();
debug_assert_eq!(*tag_id, 0);
debug_assert_eq!(**nested, Path::Empty);
let field_layouts = vec![layout.clone()]; result
}
debug_assert!(*index < field_layouts.len() as u64); fn path_to_expr_help<'a>(
env: &mut Env<'a, '_>,
mut symbol: Symbol,
path: &Path,
mut layout: Layout<'a>,
) -> (Symbol, StoresVec<'a>, Layout<'a>) {
let mut stores = bumpalo::collections::Vec::new_in(env.arena);
let inner_layout = field_layouts[*index as usize].clone(); let instructions = reverse_path(path);
let inner_expr = Expr::AccessAtIndex { let mut it = instructions.iter().peekable();
index: *index,
field_layouts: env.arena.alloc(field_layouts),
structure: symbol,
wrapped: Wrapped::SingleElementRecord,
};
symbol = env.unique_symbol(); while let Some(PathInstruction { index, tag_id }) = it.next() {
stores.push((symbol, inner_layout.clone(), inner_expr)); match Wrapped::opt_from_layout(&layout) {
None => {
// this MUST be an index into a single-element (hence unwrapped) record
break; debug_assert_eq!(*index, 0);
} debug_assert_eq!(*tag_id, 0);
Some(wrapped) => { debug_assert!(it.peek().is_none());
let field_layouts = match &layout {
Layout::Union(layouts) | Layout::RecursiveUnion(layouts) => {
layouts[*tag_id as usize].to_vec()
}
Layout::Struct(layouts) => layouts.to_vec(),
other => vec![other.clone()],
};
debug_assert!(*index < field_layouts.len() as u64); let field_layouts = vec![layout.clone()];
let inner_layout = match &field_layouts[*index as usize] { debug_assert!(*index < field_layouts.len() as u64);
Layout::RecursivePointer => layout.clone(),
other => other.clone(),
};
let inner_expr = Expr::AccessAtIndex { let inner_layout = field_layouts[*index as usize].clone();
index: *index, let inner_expr = Expr::AccessAtIndex {
field_layouts: env.arena.alloc(field_layouts), index: *index,
structure: symbol, field_layouts: env.arena.alloc(field_layouts),
wrapped, structure: symbol,
}; wrapped: Wrapped::SingleElementRecord,
};
symbol = env.unique_symbol(); symbol = env.unique_symbol();
stores.push((symbol, inner_layout.clone(), inner_expr)); stores.push((symbol, inner_layout.clone(), inner_expr));
layout = inner_layout; break;
path = nested; }
} Some(wrapped) => {
}, let field_layouts = match &layout {
Layout::Union(layouts) | Layout::RecursiveUnion(layouts) => {
layouts[*tag_id as usize]
}
Layout::Struct(layouts) => layouts,
other => env.arena.alloc([other.clone()]),
};
debug_assert!(*index < field_layouts.len() as u64);
let inner_layout = match &field_layouts[*index as usize] {
Layout::RecursivePointer => layout.clone(),
other => other.clone(),
};
let inner_expr = Expr::AccessAtIndex {
index: *index,
field_layouts,
structure: symbol,
wrapped,
};
symbol = env.unique_symbol();
stores.push((symbol, inner_layout.clone(), inner_expr));
layout = inner_layout;
}
} }
} }