mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
differentiate between 0-arity thunks and function pointers
This commit is contained in:
parent
425fd82fe9
commit
c933888690
2 changed files with 45 additions and 29 deletions
|
@ -2030,8 +2030,19 @@ pub fn with_hole<'a>(
|
||||||
);
|
);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
} else if symbol.module_id() != env.home {
|
} else if symbol.module_id() != env.home && symbol.module_id() != ModuleId::ATTR {
|
||||||
// TODO here we assume this is a 0-arity thunk. That's not true in general!
|
match layout_cache.from_var(env.arena, variable, env.subs) {
|
||||||
|
Err(e) => panic!("invalid layout {:?}", e),
|
||||||
|
Ok(Layout::FunctionPointer(_, _)) => {
|
||||||
|
specialize_imported_symbol(
|
||||||
|
env,
|
||||||
|
&mut procs.externals_we_need,
|
||||||
|
symbol,
|
||||||
|
variable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(_) => {
|
||||||
|
// this is a 0-arity thunk
|
||||||
let result = call_by_name(
|
let result = call_by_name(
|
||||||
env,
|
env,
|
||||||
procs,
|
procs,
|
||||||
|
@ -2042,9 +2053,10 @@ pub fn with_hole<'a>(
|
||||||
assigned,
|
assigned,
|
||||||
env.arena.alloc(Stmt::Ret(assigned)),
|
env.arena.alloc(Stmt::Ret(assigned)),
|
||||||
);
|
);
|
||||||
dbg!(&procs.externals_we_need);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// A bit ugly, but it does the job
|
// A bit ugly, but it does the job
|
||||||
match hole {
|
match hole {
|
||||||
|
@ -2191,7 +2203,7 @@ pub fn with_hole<'a>(
|
||||||
let mut field_symbols = Vec::with_capacity_in(fields.len(), env.arena);
|
let mut field_symbols = Vec::with_capacity_in(fields.len(), env.arena);
|
||||||
let mut can_fields = Vec::with_capacity_in(fields.len(), env.arena);
|
let mut can_fields = Vec::with_capacity_in(fields.len(), env.arena);
|
||||||
|
|
||||||
for (label, _) in sorted_fields.into_iter() {
|
for (label, _, _) in sorted_fields.into_iter() {
|
||||||
// TODO how should function pointers be handled here?
|
// TODO how should function pointers be handled here?
|
||||||
match fields.remove(&label) {
|
match fields.remove(&label) {
|
||||||
Some(field) => match can_reuse_symbol(procs, &field.loc_expr.value) {
|
Some(field) => match can_reuse_symbol(procs, &field.loc_expr.value) {
|
||||||
|
@ -2483,7 +2495,7 @@ pub fn with_hole<'a>(
|
||||||
let mut field_layouts = Vec::with_capacity_in(sorted_fields.len(), env.arena);
|
let mut field_layouts = Vec::with_capacity_in(sorted_fields.len(), env.arena);
|
||||||
|
|
||||||
let mut current = 0;
|
let mut current = 0;
|
||||||
for (label, opt_field_layout) in sorted_fields.into_iter() {
|
for (label, _, opt_field_layout) in sorted_fields.into_iter() {
|
||||||
match opt_field_layout {
|
match opt_field_layout {
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// this was an optional field, and now does not exist!
|
// this was an optional field, and now does not exist!
|
||||||
|
@ -2624,7 +2636,7 @@ pub fn with_hole<'a>(
|
||||||
let mut fields = Vec::with_capacity_in(sorted_fields.len(), env.arena);
|
let mut fields = Vec::with_capacity_in(sorted_fields.len(), env.arena);
|
||||||
|
|
||||||
let mut current = 0;
|
let mut current = 0;
|
||||||
for (label, opt_field_layout) in sorted_fields.into_iter() {
|
for (label, _, opt_field_layout) in sorted_fields.into_iter() {
|
||||||
match opt_field_layout {
|
match opt_field_layout {
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
debug_assert!(!updates.contains_key(&label));
|
debug_assert!(!updates.contains_key(&label));
|
||||||
|
@ -4086,11 +4098,10 @@ fn store_record_destruct<'a>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
DestructType::Optional(expr) => {
|
DestructType::Optional(expr) => {
|
||||||
let variable = panic!();
|
|
||||||
stmt = with_hole(
|
stmt = with_hole(
|
||||||
env,
|
env,
|
||||||
expr.clone(),
|
expr.clone(),
|
||||||
variable,
|
destruct.variable,
|
||||||
procs,
|
procs,
|
||||||
layout_cache,
|
layout_cache,
|
||||||
destruct.symbol,
|
destruct.symbol,
|
||||||
|
@ -4378,8 +4389,6 @@ fn call_by_name<'a>(
|
||||||
) -> Stmt<'a> {
|
) -> Stmt<'a> {
|
||||||
let original_fn_var = fn_var;
|
let original_fn_var = fn_var;
|
||||||
|
|
||||||
println!("call by name of {:?}", proc_name);
|
|
||||||
|
|
||||||
// Register a pending_specialization for this function
|
// Register a pending_specialization for this function
|
||||||
match layout_cache.from_var(env.arena, fn_var, env.subs) {
|
match layout_cache.from_var(env.arena, fn_var, env.subs) {
|
||||||
Ok(layout) => {
|
Ok(layout) => {
|
||||||
|
@ -4642,6 +4651,7 @@ pub enum Pattern<'a> {
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct RecordDestruct<'a> {
|
pub struct RecordDestruct<'a> {
|
||||||
pub label: Lowercase,
|
pub label: Lowercase,
|
||||||
|
pub variable: Variable,
|
||||||
pub layout: Layout<'a>,
|
pub layout: Layout<'a>,
|
||||||
pub symbol: Symbol,
|
pub symbol: Symbol,
|
||||||
pub typ: DestructType<'a>,
|
pub typ: DestructType<'a>,
|
||||||
|
@ -4868,7 +4878,7 @@ pub fn from_can_pattern<'a>(
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match (opt_sorted, opt_destruct) {
|
match (opt_sorted, opt_destruct) {
|
||||||
(Some((label, Ok(field_layout))), Some(destruct)) => {
|
(Some((label, variable, Ok(field_layout))), Some(destruct)) => {
|
||||||
if destruct.value.label == label {
|
if destruct.value.label == label {
|
||||||
mono_destructs.push(from_can_record_destruct(
|
mono_destructs.push(from_can_record_destruct(
|
||||||
env,
|
env,
|
||||||
|
@ -4884,6 +4894,7 @@ pub fn from_can_pattern<'a>(
|
||||||
mono_destructs.push(RecordDestruct {
|
mono_destructs.push(RecordDestruct {
|
||||||
label: label.clone(),
|
label: label.clone(),
|
||||||
symbol: env.unique_symbol(),
|
symbol: env.unique_symbol(),
|
||||||
|
variable,
|
||||||
layout: field_layout.clone(),
|
layout: field_layout.clone(),
|
||||||
typ: DestructType::Guard(Pattern::Underscore),
|
typ: DestructType::Guard(Pattern::Underscore),
|
||||||
});
|
});
|
||||||
|
@ -4892,7 +4903,7 @@ pub fn from_can_pattern<'a>(
|
||||||
}
|
}
|
||||||
field_layouts.push(field_layout);
|
field_layouts.push(field_layout);
|
||||||
}
|
}
|
||||||
(Some((label, Err(field_layout))), Some(destruct)) => {
|
(Some((label, variable, Err(field_layout))), Some(destruct)) => {
|
||||||
if destruct.value.label == label {
|
if destruct.value.label == label {
|
||||||
opt_destruct = it2.next();
|
opt_destruct = it2.next();
|
||||||
|
|
||||||
|
@ -4900,6 +4911,7 @@ pub fn from_can_pattern<'a>(
|
||||||
label: destruct.value.label.clone(),
|
label: destruct.value.label.clone(),
|
||||||
symbol: destruct.value.symbol,
|
symbol: destruct.value.symbol,
|
||||||
layout: field_layout,
|
layout: field_layout,
|
||||||
|
variable,
|
||||||
typ: match &destruct.value.typ {
|
typ: match &destruct.value.typ {
|
||||||
roc_can::pattern::DestructType::Optional(_, loc_expr) => {
|
roc_can::pattern::DestructType::Optional(_, loc_expr) => {
|
||||||
// if we reach this stage, the optional field is not present
|
// if we reach this stage, the optional field is not present
|
||||||
|
@ -4915,12 +4927,13 @@ pub fn from_can_pattern<'a>(
|
||||||
opt_sorted = it1.next();
|
opt_sorted = it1.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
(Some((label, Err(field_layout))), None) => {
|
(Some((label, variable, Err(field_layout))), None) => {
|
||||||
// the remainder of the fields (from the type) is not matched on in
|
// the remainder of the fields (from the type) is not matched on in
|
||||||
// this pattern; to fill it out, we put underscores
|
// this pattern; to fill it out, we put underscores
|
||||||
mono_destructs.push(RecordDestruct {
|
mono_destructs.push(RecordDestruct {
|
||||||
label: label.clone(),
|
label: label.clone(),
|
||||||
symbol: env.unique_symbol(),
|
symbol: env.unique_symbol(),
|
||||||
|
variable,
|
||||||
layout: field_layout.clone(),
|
layout: field_layout.clone(),
|
||||||
typ: DestructType::Guard(Pattern::Underscore),
|
typ: DestructType::Guard(Pattern::Underscore),
|
||||||
});
|
});
|
||||||
|
@ -4928,12 +4941,13 @@ pub fn from_can_pattern<'a>(
|
||||||
opt_sorted = it1.next();
|
opt_sorted = it1.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
(Some((label, Ok(field_layout))), None) => {
|
(Some((label, variable, Ok(field_layout))), None) => {
|
||||||
// the remainder of the fields (from the type) is not matched on in
|
// the remainder of the fields (from the type) is not matched on in
|
||||||
// this pattern; to fill it out, we put underscores
|
// this pattern; to fill it out, we put underscores
|
||||||
mono_destructs.push(RecordDestruct {
|
mono_destructs.push(RecordDestruct {
|
||||||
label: label.clone(),
|
label: label.clone(),
|
||||||
symbol: env.unique_symbol(),
|
symbol: env.unique_symbol(),
|
||||||
|
variable,
|
||||||
layout: field_layout.clone(),
|
layout: field_layout.clone(),
|
||||||
typ: DestructType::Guard(Pattern::Underscore),
|
typ: DestructType::Guard(Pattern::Underscore),
|
||||||
});
|
});
|
||||||
|
@ -4955,6 +4969,7 @@ pub fn from_can_pattern<'a>(
|
||||||
mono_destructs.push(RecordDestruct {
|
mono_destructs.push(RecordDestruct {
|
||||||
label: destruct.value.label.clone(),
|
label: destruct.value.label.clone(),
|
||||||
symbol: destruct.value.symbol,
|
symbol: destruct.value.symbol,
|
||||||
|
variable: destruct.value.var,
|
||||||
layout: field_layout,
|
layout: field_layout,
|
||||||
typ: DestructType::Optional(loc_expr.value.clone()),
|
typ: DestructType::Optional(loc_expr.value.clone()),
|
||||||
})
|
})
|
||||||
|
@ -4988,6 +5003,7 @@ fn from_can_record_destruct<'a>(
|
||||||
RecordDestruct {
|
RecordDestruct {
|
||||||
label: can_rd.label.clone(),
|
label: can_rd.label.clone(),
|
||||||
symbol: can_rd.symbol,
|
symbol: can_rd.symbol,
|
||||||
|
variable: can_rd.var,
|
||||||
layout: field_layout,
|
layout: field_layout,
|
||||||
typ: match &can_rd.typ {
|
typ: match &can_rd.typ {
|
||||||
roc_can::pattern::DestructType::Required => DestructType::Required,
|
roc_can::pattern::DestructType::Required => DestructType::Required,
|
||||||
|
|
|
@ -822,7 +822,7 @@ pub fn sort_record_fields<'a>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
var: Variable,
|
var: Variable,
|
||||||
subs: &Subs,
|
subs: &Subs,
|
||||||
) -> Vec<'a, (Lowercase, Result<Layout<'a>, Layout<'a>>)> {
|
) -> Vec<'a, (Lowercase, Variable, Result<Layout<'a>, Layout<'a>>)> {
|
||||||
let mut fields_map = MutMap::default();
|
let mut fields_map = MutMap::default();
|
||||||
|
|
||||||
let mut env = Env {
|
let mut env = Env {
|
||||||
|
@ -844,7 +844,7 @@ pub fn sort_record_fields<'a>(
|
||||||
RecordField::Optional(v) => {
|
RecordField::Optional(v) => {
|
||||||
let layout =
|
let layout =
|
||||||
Layout::from_var(&mut env, v).expect("invalid layout from var");
|
Layout::from_var(&mut env, v).expect("invalid layout from var");
|
||||||
sorted_fields.push((label, Err(layout)));
|
sorted_fields.push((label, v, Err(layout)));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -853,11 +853,11 @@ pub fn sort_record_fields<'a>(
|
||||||
|
|
||||||
// Drop any zero-sized fields like {}
|
// Drop any zero-sized fields like {}
|
||||||
if !layout.is_zero_sized() {
|
if !layout.is_zero_sized() {
|
||||||
sorted_fields.push((label, Ok(layout)));
|
sorted_fields.push((label, var, Ok(layout)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sorted_fields.sort_by(|(label1, _), (label2, _)| label1.cmp(label2));
|
sorted_fields.sort_by(|(label1, _, _), (label2, _, _)| label1.cmp(label2));
|
||||||
|
|
||||||
sorted_fields
|
sorted_fields
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue