mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 12:18:19 +00:00
Merge branch 'main' into builtin-task
This commit is contained in:
commit
7e72541a79
82 changed files with 2468 additions and 1003 deletions
|
@ -467,7 +467,8 @@ pub fn find_type_def_symbols(
|
|||
while let Some(assigned_field) = inner_stack.pop() {
|
||||
match assigned_field {
|
||||
AssignedField::RequiredValue(_, _, t)
|
||||
| AssignedField::OptionalValue(_, _, t) => {
|
||||
| AssignedField::OptionalValue(_, _, t)
|
||||
| AssignedField::IgnoredValue(_, _, t) => {
|
||||
stack.push(&t.value);
|
||||
}
|
||||
AssignedField::LabelOnly(_) => {}
|
||||
|
@ -1386,6 +1387,7 @@ fn can_assigned_fields<'a>(
|
|||
|
||||
break 'inner label;
|
||||
}
|
||||
IgnoredValue(_, _, _) => unreachable!(),
|
||||
LabelOnly(loc_field_name) => {
|
||||
// Interpret { a, b } as { a : a, b : b }
|
||||
let field_name = Lowercase::from(loc_field_name.value);
|
||||
|
|
|
@ -631,7 +631,9 @@ fn canonicalize_claimed_ability_impl<'a>(
|
|||
// An error will already have been reported
|
||||
Err(())
|
||||
}
|
||||
AssignedField::SpaceBefore(_, _) | AssignedField::SpaceAfter(_, _) => {
|
||||
AssignedField::SpaceBefore(_, _)
|
||||
| AssignedField::SpaceAfter(_, _)
|
||||
| AssignedField::IgnoredValue(_, _, _) => {
|
||||
internal_error!("unreachable")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -521,44 +521,68 @@ pub fn desugar_expr<'a>(
|
|||
});
|
||||
}
|
||||
|
||||
let mut field_names = Vec::with_capacity_in(fields.len(), arena);
|
||||
let mut field_vals = Vec::with_capacity_in(fields.len(), arena);
|
||||
|
||||
for field in fields.items {
|
||||
match desugar_field(arena, &field.value, src, line_info, module_path) {
|
||||
AssignedField::RequiredValue(loc_name, _, loc_val) => {
|
||||
field_names.push(loc_name);
|
||||
field_vals.push(loc_val);
|
||||
}
|
||||
AssignedField::LabelOnly(loc_name) => {
|
||||
field_names.push(loc_name);
|
||||
field_vals.push(arena.alloc(Loc {
|
||||
region: loc_name.region,
|
||||
value: Expr::Var {
|
||||
module_name: "",
|
||||
ident: loc_name.value,
|
||||
},
|
||||
}));
|
||||
}
|
||||
AssignedField::OptionalValue(loc_name, _, loc_val) => {
|
||||
return arena.alloc(Loc {
|
||||
region: loc_expr.region,
|
||||
value: OptionalFieldInRecordBuilder(arena.alloc(loc_name), loc_val),
|
||||
});
|
||||
}
|
||||
AssignedField::SpaceBefore(_, _) | AssignedField::SpaceAfter(_, _) => {
|
||||
unreachable!("Should have been desugared in `desugar_field`")
|
||||
}
|
||||
AssignedField::Malformed(_name) => {}
|
||||
}
|
||||
struct FieldData<'d> {
|
||||
name: Loc<&'d str>,
|
||||
value: &'d Loc<Expr<'d>>,
|
||||
ignored: bool,
|
||||
}
|
||||
|
||||
let closure_arg_from_field = |field: Loc<&'a str>| Loc {
|
||||
region: field.region,
|
||||
value: Pattern::Identifier {
|
||||
ident: arena.alloc_str(&format!("#{}", field.value)),
|
||||
},
|
||||
};
|
||||
let mut field_data = Vec::with_capacity_in(fields.len(), arena);
|
||||
|
||||
for field in fields.items {
|
||||
let (name, value, ignored) =
|
||||
match desugar_field(arena, &field.value, src, line_info, module_path) {
|
||||
AssignedField::RequiredValue(loc_name, _, loc_val) => {
|
||||
(loc_name, loc_val, false)
|
||||
}
|
||||
AssignedField::IgnoredValue(loc_name, _, loc_val) => {
|
||||
(loc_name, loc_val, true)
|
||||
}
|
||||
AssignedField::LabelOnly(loc_name) => (
|
||||
loc_name,
|
||||
&*arena.alloc(Loc {
|
||||
region: loc_name.region,
|
||||
value: Expr::Var {
|
||||
module_name: "",
|
||||
ident: loc_name.value,
|
||||
},
|
||||
}),
|
||||
false,
|
||||
),
|
||||
AssignedField::OptionalValue(loc_name, _, loc_val) => {
|
||||
return arena.alloc(Loc {
|
||||
region: loc_expr.region,
|
||||
value: OptionalFieldInRecordBuilder(arena.alloc(loc_name), loc_val),
|
||||
});
|
||||
}
|
||||
AssignedField::SpaceBefore(_, _) | AssignedField::SpaceAfter(_, _) => {
|
||||
unreachable!("Should have been desugared in `desugar_field`")
|
||||
}
|
||||
AssignedField::Malformed(_name) => continue,
|
||||
};
|
||||
|
||||
field_data.push(FieldData {
|
||||
name,
|
||||
value,
|
||||
ignored,
|
||||
});
|
||||
}
|
||||
|
||||
let closure_arg_from_field =
|
||||
|FieldData {
|
||||
name,
|
||||
value: _,
|
||||
ignored,
|
||||
}: &FieldData<'a>| Loc {
|
||||
region: name.region,
|
||||
value: if *ignored {
|
||||
Pattern::Underscore(name.value)
|
||||
} else {
|
||||
Pattern::Identifier {
|
||||
ident: arena.alloc_str(&format!("#{}", name.value)),
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let combiner_closure_in_region = |region| {
|
||||
let closure_body = Tuple(Collection::with_items(
|
||||
|
@ -607,15 +631,15 @@ pub fn desugar_expr<'a>(
|
|||
};
|
||||
|
||||
let closure_args = {
|
||||
if field_names.len() == 2 {
|
||||
if field_data.len() == 2 {
|
||||
arena.alloc_slice_copy(&[
|
||||
closure_arg_from_field(field_names[0]),
|
||||
closure_arg_from_field(field_names[1]),
|
||||
closure_arg_from_field(&field_data[0]),
|
||||
closure_arg_from_field(&field_data[1]),
|
||||
])
|
||||
} else {
|
||||
let second_to_last_arg =
|
||||
closure_arg_from_field(field_names[field_names.len() - 2]);
|
||||
let last_arg = closure_arg_from_field(field_names[field_names.len() - 1]);
|
||||
closure_arg_from_field(&field_data[field_data.len() - 2]);
|
||||
let last_arg = closure_arg_from_field(&field_data[field_data.len() - 1]);
|
||||
|
||||
let mut second_arg = Pattern::Tuple(Collection::with_items(
|
||||
arena.alloc_slice_copy(&[second_to_last_arg, last_arg]),
|
||||
|
@ -623,18 +647,18 @@ pub fn desugar_expr<'a>(
|
|||
let mut second_arg_region =
|
||||
Region::span_across(&second_to_last_arg.region, &last_arg.region);
|
||||
|
||||
for index in (1..(field_names.len() - 2)).rev() {
|
||||
for index in (1..(field_data.len() - 2)).rev() {
|
||||
second_arg =
|
||||
Pattern::Tuple(Collection::with_items(arena.alloc_slice_copy(&[
|
||||
closure_arg_from_field(field_names[index]),
|
||||
closure_arg_from_field(&field_data[index]),
|
||||
Loc::at(second_arg_region, second_arg),
|
||||
])));
|
||||
second_arg_region =
|
||||
Region::span_across(&field_names[index].region, &second_arg_region);
|
||||
Region::span_across(&field_data[index].name.region, &second_arg_region);
|
||||
}
|
||||
|
||||
arena.alloc_slice_copy(&[
|
||||
closure_arg_from_field(field_names[0]),
|
||||
closure_arg_from_field(&field_data[0]),
|
||||
Loc::at(second_arg_region, second_arg),
|
||||
])
|
||||
}
|
||||
|
@ -642,22 +666,26 @@ pub fn desugar_expr<'a>(
|
|||
|
||||
let record_val = Record(Collection::with_items(
|
||||
Vec::from_iter_in(
|
||||
field_names.iter().map(|field_name| {
|
||||
Loc::at(
|
||||
field_name.region,
|
||||
AssignedField::RequiredValue(
|
||||
Loc::at(field_name.region, field_name.value),
|
||||
&[],
|
||||
arena.alloc(Loc::at(
|
||||
field_name.region,
|
||||
Expr::Var {
|
||||
module_name: "",
|
||||
ident: arena.alloc_str(&format!("#{}", field_name.value)),
|
||||
},
|
||||
)),
|
||||
),
|
||||
)
|
||||
}),
|
||||
field_data
|
||||
.iter()
|
||||
.filter(|field| !field.ignored)
|
||||
.map(|field| {
|
||||
Loc::at(
|
||||
field.name.region,
|
||||
AssignedField::RequiredValue(
|
||||
field.name,
|
||||
&[],
|
||||
arena.alloc(Loc::at(
|
||||
field.name.region,
|
||||
Expr::Var {
|
||||
module_name: "",
|
||||
ident: arena
|
||||
.alloc_str(&format!("#{}", field.name.value)),
|
||||
},
|
||||
)),
|
||||
),
|
||||
)
|
||||
}),
|
||||
arena,
|
||||
)
|
||||
.into_bump_slice(),
|
||||
|
@ -671,14 +699,14 @@ pub fn desugar_expr<'a>(
|
|||
),
|
||||
});
|
||||
|
||||
if field_names.len() == 2 {
|
||||
if field_data.len() == 2 {
|
||||
return arena.alloc(Loc {
|
||||
region: loc_expr.region,
|
||||
value: Apply(
|
||||
new_mapper,
|
||||
arena.alloc_slice_copy(&[
|
||||
field_vals[0],
|
||||
field_vals[1],
|
||||
field_data[0].value,
|
||||
field_data[1].value,
|
||||
record_combiner_closure,
|
||||
]),
|
||||
CalledVia::RecordBuilder,
|
||||
|
@ -688,27 +716,30 @@ pub fn desugar_expr<'a>(
|
|||
|
||||
let mut inner_combined = arena.alloc(Loc {
|
||||
region: Region::span_across(
|
||||
&field_vals[field_names.len() - 2].region,
|
||||
&field_vals[field_names.len() - 1].region,
|
||||
&field_data[field_data.len() - 2].value.region,
|
||||
&field_data[field_data.len() - 1].value.region,
|
||||
),
|
||||
value: Apply(
|
||||
new_mapper,
|
||||
arena.alloc_slice_copy(&[
|
||||
field_vals[field_names.len() - 2],
|
||||
field_vals[field_names.len() - 1],
|
||||
field_data[field_data.len() - 2].value,
|
||||
field_data[field_data.len() - 1].value,
|
||||
combiner_closure_in_region(loc_expr.region),
|
||||
]),
|
||||
CalledVia::RecordBuilder,
|
||||
),
|
||||
});
|
||||
|
||||
for index in (1..(field_names.len() - 2)).rev() {
|
||||
for index in (1..(field_data.len() - 2)).rev() {
|
||||
inner_combined = arena.alloc(Loc {
|
||||
region: Region::span_across(&field_vals[index].region, &inner_combined.region),
|
||||
region: Region::span_across(
|
||||
&field_data[index].value.region,
|
||||
&inner_combined.region,
|
||||
),
|
||||
value: Apply(
|
||||
new_mapper,
|
||||
arena.alloc_slice_copy(&[
|
||||
field_vals[index],
|
||||
field_data[index].value,
|
||||
inner_combined,
|
||||
combiner_closure_in_region(loc_expr.region),
|
||||
]),
|
||||
|
@ -722,7 +753,7 @@ pub fn desugar_expr<'a>(
|
|||
value: Apply(
|
||||
new_mapper,
|
||||
arena.alloc_slice_copy(&[
|
||||
field_vals[0],
|
||||
field_data[0].value,
|
||||
inner_combined,
|
||||
record_combiner_closure,
|
||||
]),
|
||||
|
@ -1095,6 +1126,14 @@ fn desugar_field<'a>(
|
|||
spaces,
|
||||
desugar_expr(arena, loc_expr, src, line_info, module_path),
|
||||
),
|
||||
IgnoredValue(loc_str, spaces, loc_expr) => IgnoredValue(
|
||||
Loc {
|
||||
value: loc_str.value,
|
||||
region: loc_str.region,
|
||||
},
|
||||
spaces,
|
||||
desugar_expr(arena, loc_expr, src, line_info, module_path),
|
||||
),
|
||||
LabelOnly(loc_str) => {
|
||||
// Desugar { x } into { x: x }
|
||||
let loc_expr = Loc {
|
||||
|
|
|
@ -1846,6 +1846,11 @@ fn canonicalize_field<'a>(
|
|||
field_region: Region::span_across(&label.region, &loc_expr.region),
|
||||
}),
|
||||
|
||||
// An ignored value, e.g. `{ _name: 123 }`
|
||||
IgnoredValue(_, _, _) => {
|
||||
internal_error!("Somehow an IgnoredValue record field was not desugared!");
|
||||
}
|
||||
|
||||
// A label with no value, e.g. `{ name }` (this is sugar for { name: name })
|
||||
LabelOnly(_) => {
|
||||
internal_error!("Somehow a LabelOnly record field was not desugared!");
|
||||
|
@ -2433,7 +2438,8 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
|||
}
|
||||
ast::Expr::Record(fields) => fields.iter().all(|loc_field| match loc_field.value {
|
||||
ast::AssignedField::RequiredValue(_label, loc_comments, loc_val)
|
||||
| ast::AssignedField::OptionalValue(_label, loc_comments, loc_val) => {
|
||||
| ast::AssignedField::OptionalValue(_label, loc_comments, loc_val)
|
||||
| ast::AssignedField::IgnoredValue(_label, loc_comments, loc_val) => {
|
||||
loc_comments.is_empty() && is_valid_interpolation(&loc_val.value)
|
||||
}
|
||||
ast::AssignedField::Malformed(_) | ast::AssignedField::LabelOnly(_) => true,
|
||||
|
@ -2481,7 +2487,8 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
|||
is_valid_interpolation(&update.value)
|
||||
&& fields.iter().all(|loc_field| match loc_field.value {
|
||||
ast::AssignedField::RequiredValue(_label, loc_comments, loc_val)
|
||||
| ast::AssignedField::OptionalValue(_label, loc_comments, loc_val) => {
|
||||
| ast::AssignedField::OptionalValue(_label, loc_comments, loc_val)
|
||||
| ast::AssignedField::IgnoredValue(_label, loc_comments, loc_val) => {
|
||||
loc_comments.is_empty() && is_valid_interpolation(&loc_val.value)
|
||||
}
|
||||
ast::AssignedField::Malformed(_) | ast::AssignedField::LabelOnly(_) => true,
|
||||
|
@ -2514,7 +2521,8 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
|||
is_valid_interpolation(&mapper.value)
|
||||
&& fields.iter().all(|loc_field| match loc_field.value {
|
||||
ast::AssignedField::RequiredValue(_label, loc_comments, loc_val)
|
||||
| ast::AssignedField::OptionalValue(_label, loc_comments, loc_val) => {
|
||||
| ast::AssignedField::OptionalValue(_label, loc_comments, loc_val)
|
||||
| ast::AssignedField::IgnoredValue(_label, loc_comments, loc_val) => {
|
||||
loc_comments.is_empty() && is_valid_interpolation(&loc_val.value)
|
||||
}
|
||||
ast::AssignedField::Malformed(_) | ast::AssignedField::LabelOnly(_) => true,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue