mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
refactor Access into AccessAtIndex
This commit is contained in:
parent
18f34710e1
commit
e2a7c970bc
4 changed files with 43 additions and 94 deletions
|
@ -281,36 +281,6 @@ pub fn build_expr<'a, B: Backend>(
|
||||||
.ins()
|
.ins()
|
||||||
.stack_addr(cfg.pointer_type(), slot, Offset32::new(0))
|
.stack_addr(cfg.pointer_type(), slot, Offset32::new(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
Access {
|
|
||||||
label,
|
|
||||||
field_layout,
|
|
||||||
struct_layout: Layout::Struct(sorted_fields),
|
|
||||||
record,
|
|
||||||
} => {
|
|
||||||
let cfg = env.cfg;
|
|
||||||
|
|
||||||
// Find the offset we are trying to access
|
|
||||||
let mut offset = 0;
|
|
||||||
for (local_label, local_field_layout) in sorted_fields.iter() {
|
|
||||||
if local_label == label {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset += local_field_layout.stack_size(ptr_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
let offset = i32::try_from(offset)
|
|
||||||
.expect("TODO gracefully handle usize -> i32 conversion in struct access");
|
|
||||||
|
|
||||||
let mem_flags = MemFlags::new();
|
|
||||||
let record = build_expr(env, scope, module, builder, record, procs);
|
|
||||||
let field_type = type_from_layout(cfg, field_layout);
|
|
||||||
|
|
||||||
builder
|
|
||||||
.ins()
|
|
||||||
.load(field_type, mem_flags, record, Offset32::new(offset))
|
|
||||||
}
|
|
||||||
AccessAtIndex {
|
AccessAtIndex {
|
||||||
index,
|
index,
|
||||||
field_layouts,
|
field_layouts,
|
||||||
|
|
|
@ -72,9 +72,6 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
build_branch2(env, scope, parent, conditional, procs)
|
build_branch2(env, scope, parent, conditional, procs)
|
||||||
}
|
}
|
||||||
Branches { .. } => {
|
|
||||||
panic!("TODO build_branches(env, scope, parent, cond_lhs, branches, procs)");
|
|
||||||
}
|
|
||||||
Switch {
|
Switch {
|
||||||
cond,
|
cond,
|
||||||
branches,
|
branches,
|
||||||
|
@ -476,27 +473,6 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
.unwrap();
|
.unwrap();
|
||||||
wrapper_val.into_struct_value().into()
|
wrapper_val.into_struct_value().into()
|
||||||
}
|
}
|
||||||
Access {
|
|
||||||
label,
|
|
||||||
struct_layout: Layout::Struct(sorted_fields),
|
|
||||||
record,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let builder = env.builder;
|
|
||||||
|
|
||||||
// Get index
|
|
||||||
let index = sorted_fields
|
|
||||||
.iter()
|
|
||||||
.position(|(local_label, _)| local_label == label)
|
|
||||||
.unwrap() as u32; // TODO
|
|
||||||
|
|
||||||
// Get Struct val
|
|
||||||
let struct_val = build_expr(env, &scope, parent, record, procs).into_struct_value();
|
|
||||||
|
|
||||||
builder
|
|
||||||
.build_extract_value(struct_val, index, "field_access")
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
AccessAtIndex {
|
AccessAtIndex {
|
||||||
index,
|
index,
|
||||||
expr,
|
expr,
|
||||||
|
|
|
@ -159,16 +159,6 @@ pub enum Expr<'a> {
|
||||||
fail: &'a Expr<'a>,
|
fail: &'a Expr<'a>,
|
||||||
ret_layout: Layout<'a>,
|
ret_layout: Layout<'a>,
|
||||||
},
|
},
|
||||||
/// More than two conditional branches, e.g. a 3-way when-expression
|
|
||||||
Branches {
|
|
||||||
/// The left-hand side of the conditional. We compile this to LLVM once,
|
|
||||||
/// then reuse it to test against each different compiled cond_rhs value.
|
|
||||||
cond: &'a Expr<'a>,
|
|
||||||
/// ( cond_rhs, pass, fail )
|
|
||||||
branches: &'a [(Expr<'a>, Expr<'a>, Expr<'a>)],
|
|
||||||
default: &'a Expr<'a>,
|
|
||||||
ret_layout: Layout<'a>,
|
|
||||||
},
|
|
||||||
/// Conditional branches for integers. These are more efficient.
|
/// Conditional branches for integers. These are more efficient.
|
||||||
Switch {
|
Switch {
|
||||||
/// This *must* be an integer, because Switch potentially compiles to a jump table.
|
/// This *must* be an integer, because Switch potentially compiles to a jump table.
|
||||||
|
@ -190,12 +180,6 @@ pub enum Expr<'a> {
|
||||||
arguments: &'a [(Expr<'a>, Layout<'a>)],
|
arguments: &'a [(Expr<'a>, Layout<'a>)],
|
||||||
},
|
},
|
||||||
Struct(&'a [(Expr<'a>, Layout<'a>)]),
|
Struct(&'a [(Expr<'a>, Layout<'a>)]),
|
||||||
Access {
|
|
||||||
label: Lowercase,
|
|
||||||
field_layout: Layout<'a>,
|
|
||||||
struct_layout: Layout<'a>,
|
|
||||||
record: &'a Expr<'a>,
|
|
||||||
},
|
|
||||||
AccessAtIndex {
|
AccessAtIndex {
|
||||||
index: u64,
|
index: u64,
|
||||||
field_layouts: &'a [Layout<'a>],
|
field_layouts: &'a [Layout<'a>],
|
||||||
|
@ -772,14 +756,13 @@ fn from_can<'a>(
|
||||||
|
|
||||||
Access {
|
Access {
|
||||||
record_var,
|
record_var,
|
||||||
field_var,
|
|
||||||
field,
|
field,
|
||||||
loc_expr,
|
loc_expr,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let arena = env.arena;
|
let arena = env.arena;
|
||||||
|
|
||||||
let struct_layout =
|
let record_layout =
|
||||||
match Layout::from_var(arena, record_var, env.subs, env.pointer_size) {
|
match Layout::from_var(arena, record_var, env.subs, env.pointer_size) {
|
||||||
Ok(layout) => layout,
|
Ok(layout) => layout,
|
||||||
Err(()) => {
|
Err(()) => {
|
||||||
|
@ -788,23 +771,9 @@ fn from_can<'a>(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let field_layout = match Layout::from_var(arena, field_var, env.subs, env.pointer_size)
|
|
||||||
{
|
|
||||||
Ok(layout) => layout,
|
|
||||||
Err(()) => {
|
|
||||||
// Invalid field!
|
|
||||||
panic!("TODO gracefully handle Access with invalid field_layout");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let record = arena.alloc(from_can(env, loc_expr.value, procs, None));
|
let record = arena.alloc(from_can(env, loc_expr.value, procs, None));
|
||||||
|
|
||||||
Expr::Access {
|
record_access_by_field(env, record_layout, record, field)
|
||||||
label: field,
|
|
||||||
field_layout,
|
|
||||||
struct_layout,
|
|
||||||
record,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List {
|
List {
|
||||||
|
@ -841,6 +810,45 @@ fn from_can<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn record_access_by_field<'a>(
|
||||||
|
env: &mut Env<'a, '_>,
|
||||||
|
record_layout: Layout<'a>,
|
||||||
|
record_expr: &'a Expr<'a>,
|
||||||
|
field: Lowercase,
|
||||||
|
) -> Expr<'a> {
|
||||||
|
let (field_layouts, index) = match record_layout {
|
||||||
|
Layout::Struct(sorted_fields) => {
|
||||||
|
let index = sorted_fields
|
||||||
|
.iter()
|
||||||
|
.position(|(local_label, _)| local_label == &field)
|
||||||
|
.unwrap() as u64;
|
||||||
|
|
||||||
|
let mut only_fields = Vec::with_capacity_in(sorted_fields.len(), env.arena);
|
||||||
|
|
||||||
|
for (_, field) in sorted_fields.iter() {
|
||||||
|
only_fields.push(field.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
(only_fields.into_bump_slice(), index)
|
||||||
|
}
|
||||||
|
|
||||||
|
other => {
|
||||||
|
// Invalid field!
|
||||||
|
panic!(
|
||||||
|
"TODO gracefully handle Access with invalid struct_layout {:?}",
|
||||||
|
other
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Expr::AccessAtIndex {
|
||||||
|
index,
|
||||||
|
field_layouts,
|
||||||
|
expr: record_expr,
|
||||||
|
is_unwrapped: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn store_pattern<'a>(
|
fn store_pattern<'a>(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
can_pat: &Pattern<'a>,
|
can_pat: &Pattern<'a>,
|
||||||
|
@ -931,12 +939,7 @@ fn store_record_destruct<'a>(
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
use Pattern::*;
|
use Pattern::*;
|
||||||
let record = env.arena.alloc(Expr::Load(outer_symbol));
|
let record = env.arena.alloc(Expr::Load(outer_symbol));
|
||||||
let load = Expr::Access {
|
let load = record_access_by_field(env, struct_layout, record, destruct.label.clone());
|
||||||
label: destruct.label.clone(),
|
|
||||||
field_layout: destruct.layout.clone(),
|
|
||||||
struct_layout,
|
|
||||||
record,
|
|
||||||
};
|
|
||||||
match &destruct.guard {
|
match &destruct.guard {
|
||||||
None => {
|
None => {
|
||||||
stored.push((destruct.symbol, destruct.layout.clone(), load));
|
stored.push((destruct.symbol, destruct.layout.clone(), load));
|
||||||
|
|
|
@ -95,7 +95,7 @@ impl<'a> Layout<'a> {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
Pointer(_) => {
|
Pointer(_) => {
|
||||||
// We cannot memcpy pointers, because then we would have the same pointer in multiple places!
|
// We cannot memcpy pointers, because then we would have the same pointer in multiple places!
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue