mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 08:11:12 +00:00
simplify handling of optional fields
This commit is contained in:
parent
9c7514c449
commit
517f8f4a4a
1 changed files with 79 additions and 102 deletions
|
@ -5374,8 +5374,8 @@ pub fn from_can_pattern<'a>(
|
||||||
|
|
||||||
// sorted fields based on the destruct
|
// sorted fields based on the destruct
|
||||||
let mut mono_destructs = Vec::with_capacity_in(destructs.len(), env.arena);
|
let mut mono_destructs = Vec::with_capacity_in(destructs.len(), env.arena);
|
||||||
let mut destructs = destructs.clone();
|
let destructs_by_label = env.arena.alloc(MutMap::default());
|
||||||
destructs.sort_by(|a, b| a.value.label.cmp(&b.value.label));
|
destructs_by_label.extend(destructs.iter().map(|x| (&x.value.label, x)));
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
@ -5387,27 +5387,25 @@ pub fn from_can_pattern<'a>(
|
||||||
// in the source the field is not matche in the source language.
|
// in the source the field is not matche in the source language.
|
||||||
//
|
//
|
||||||
// Optional fields somewhat complicate the matter here
|
// Optional fields somewhat complicate the matter here
|
||||||
let mut it1 = sorted_fields.into_iter();
|
|
||||||
let mut opt_sorted = it1.next();
|
|
||||||
|
|
||||||
let mut it2 = destructs.iter();
|
for (label, variable, res_layout) in sorted_fields.into_iter() {
|
||||||
let mut opt_destruct = it2.next();
|
match res_layout {
|
||||||
|
Ok(field_layout) => {
|
||||||
|
// the field is non-optional according to the type
|
||||||
|
|
||||||
loop {
|
match destructs_by_label.remove(&label) {
|
||||||
match (opt_sorted, opt_destruct) {
|
Some(destruct) => {
|
||||||
(Some((label, variable, Ok(field_layout))), Some(destruct)) => {
|
// this field is destructured by the pattern
|
||||||
if destruct.value.label == label {
|
|
||||||
mono_destructs.push(from_can_record_destruct(
|
mono_destructs.push(from_can_record_destruct(
|
||||||
env,
|
env,
|
||||||
layout_cache,
|
layout_cache,
|
||||||
&destruct.value,
|
&destruct.value,
|
||||||
field_layout.clone(),
|
field_layout.clone(),
|
||||||
));
|
));
|
||||||
|
}
|
||||||
opt_sorted = it1.next();
|
None => {
|
||||||
opt_destruct = it2.next();
|
// this field is not destructured by the pattern
|
||||||
} else {
|
// put in an underscore
|
||||||
// insert underscore pattern
|
|
||||||
mono_destructs.push(RecordDestruct {
|
mono_destructs.push(RecordDestruct {
|
||||||
label: label.clone(),
|
label: label.clone(),
|
||||||
symbol: env.unique_symbol(),
|
symbol: env.unique_symbol(),
|
||||||
|
@ -5415,15 +5413,17 @@ pub fn from_can_pattern<'a>(
|
||||||
layout: field_layout.clone(),
|
layout: field_layout.clone(),
|
||||||
typ: DestructType::Guard(Pattern::Underscore),
|
typ: DestructType::Guard(Pattern::Underscore),
|
||||||
});
|
});
|
||||||
|
|
||||||
opt_sorted = it1.next();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the layout of this field is part of the layout of the record
|
||||||
field_layouts.push(field_layout);
|
field_layouts.push(field_layout);
|
||||||
}
|
}
|
||||||
(Some((label, variable, Err(field_layout))), Some(destruct)) => {
|
Err(field_layout) => {
|
||||||
if destruct.value.label == label {
|
// the field is optional according to the type
|
||||||
opt_destruct = it2.next();
|
match destructs_by_label.remove(&label) {
|
||||||
|
Some(destruct) => {
|
||||||
|
// this field is destructured by the pattern
|
||||||
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,
|
||||||
|
@ -5441,12 +5441,9 @@ pub fn from_can_pattern<'a>(
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
opt_sorted = it1.next();
|
None => {
|
||||||
}
|
// this field is not destructured by the pattern
|
||||||
|
// put in an underscore
|
||||||
(Some((label, variable, Err(field_layout))), None) => {
|
|
||||||
// the remainder of the fields (from the type) is not matched on in
|
|
||||||
// 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(),
|
||||||
|
@ -5454,26 +5451,14 @@ pub fn from_can_pattern<'a>(
|
||||||
layout: field_layout.clone(),
|
layout: field_layout.clone(),
|
||||||
typ: DestructType::Guard(Pattern::Underscore),
|
typ: DestructType::Guard(Pattern::Underscore),
|
||||||
});
|
});
|
||||||
|
}
|
||||||
opt_sorted = it1.next();
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(Some((label, variable, Ok(field_layout))), None) => {
|
for (_, destruct) in destructs_by_label.drain() {
|
||||||
// the remainder of the fields (from the type) is not matched on in
|
// this destruct is not in the type, but is in the pattern
|
||||||
// this pattern; to fill it out, we put underscores
|
|
||||||
mono_destructs.push(RecordDestruct {
|
|
||||||
label: label.clone(),
|
|
||||||
symbol: env.unique_symbol(),
|
|
||||||
variable,
|
|
||||||
layout: field_layout.clone(),
|
|
||||||
typ: DestructType::Guard(Pattern::Underscore),
|
|
||||||
});
|
|
||||||
|
|
||||||
field_layouts.push(field_layout);
|
|
||||||
opt_sorted = it1.next();
|
|
||||||
}
|
|
||||||
(None, Some(destruct)) => {
|
|
||||||
// destruct is not in the type, but is in the pattern
|
|
||||||
// it must be an optional field, and we will use the default
|
// it must be an optional field, and we will use the default
|
||||||
match &destruct.value.typ {
|
match &destruct.value.typ {
|
||||||
roc_can::pattern::DestructType::Optional(field_var, loc_expr) => {
|
roc_can::pattern::DestructType::Optional(field_var, loc_expr) => {
|
||||||
|
@ -5493,14 +5478,6 @@ pub fn from_can_pattern<'a>(
|
||||||
}
|
}
|
||||||
_ => unreachable!("only optional destructs can be optional fields"),
|
_ => unreachable!("only optional destructs can be optional fields"),
|
||||||
}
|
}
|
||||||
|
|
||||||
opt_sorted = None;
|
|
||||||
opt_destruct = it2.next();
|
|
||||||
}
|
|
||||||
(None, None) => {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Pattern::RecordDestructure(
|
Pattern::RecordDestructure(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue