differentiate between 0-arity thunks and function pointers

This commit is contained in:
Folkert 2020-11-02 22:50:12 +01:00
parent 425fd82fe9
commit c933888690
2 changed files with 45 additions and 29 deletions

View file

@ -2030,20 +2030,32 @@ 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) {
let result = call_by_name( Err(e) => panic!("invalid layout {:?}", e),
env, Ok(Layout::FunctionPointer(_, _)) => {
procs, specialize_imported_symbol(
variable, env,
symbol, &mut procs.externals_we_need,
std::vec::Vec::new(), symbol,
layout_cache, variable,
assigned, );
env.arena.alloc(Stmt::Ret(assigned)), }
); Ok(_) => {
dbg!(&procs.externals_we_need); // this is a 0-arity thunk
return result; let result = call_by_name(
env,
procs,
variable,
symbol,
std::vec::Vec::new(),
layout_cache,
assigned,
env.arena.alloc(Stmt::Ret(assigned)),
);
return result;
}
}
} }
// A bit ugly, but it does the job // A bit ugly, but it does the job
@ -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,

View file

@ -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
} }