mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
Merge branch 'trunk' into fix-uniq-principality
This commit is contained in:
commit
e019a4b662
8 changed files with 82 additions and 28 deletions
|
@ -73,8 +73,9 @@ pub fn fmt_expr<'a>(
|
||||||
}
|
}
|
||||||
buf.push_str("\"\"\"");
|
buf.push_str("\"\"\"");
|
||||||
}
|
}
|
||||||
Int(string) => buf.push_str(string),
|
Int(string) | Float(string) | GlobalTag(string) | PrivateTag(string) => {
|
||||||
Float(string) => buf.push_str(string),
|
buf.push_str(string)
|
||||||
|
}
|
||||||
NonBase10Int {
|
NonBase10Int {
|
||||||
base,
|
base,
|
||||||
string,
|
string,
|
||||||
|
@ -480,7 +481,7 @@ pub fn fmt_closure<'a>(
|
||||||
any_args_printed = true;
|
any_args_printed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt_pattern(buf, &loc_pattern.value, indent, true);
|
fmt_pattern(buf, &loc_pattern.value, indent, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !arguments_are_multiline {
|
if !arguments_are_multiline {
|
||||||
|
|
|
@ -430,7 +430,7 @@ pub fn loc_parenthetical_def<'a>(min_indent: u16) -> impl Parser<'a, Located<Exp
|
||||||
space0_after(
|
space0_after(
|
||||||
between!(
|
between!(
|
||||||
char('('),
|
char('('),
|
||||||
space0_around(loc!(pattern(min_indent)), min_indent),
|
space0_around(loc_pattern(min_indent), min_indent),
|
||||||
char(')')
|
char(')')
|
||||||
),
|
),
|
||||||
min_indent,
|
min_indent,
|
||||||
|
@ -752,23 +752,32 @@ fn parse_closure_param<'a>(
|
||||||
// e.g. \User.UserId userId -> ...
|
// e.g. \User.UserId userId -> ...
|
||||||
between!(
|
between!(
|
||||||
char('('),
|
char('('),
|
||||||
space0_around(loc!(pattern(min_indent)), min_indent),
|
space0_around(loc_pattern(min_indent), min_indent),
|
||||||
char(')')
|
char(')')
|
||||||
),
|
),
|
||||||
// The least common, but still allowed, e.g. \Foo -> ...
|
// The least common, but still allowed, e.g. \Foo -> ...
|
||||||
loc!(tag_pattern())
|
loc_tag_pattern(min_indent)
|
||||||
)
|
)
|
||||||
.parse(arena, state)
|
.parse(arena, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pattern<'a>(min_indent: u16) -> impl Parser<'a, Pattern<'a>> {
|
fn loc_pattern<'a>(min_indent: u16) -> impl Parser<'a, Located<Pattern<'a>>> {
|
||||||
one_of!(
|
one_of!(
|
||||||
underscore_pattern(),
|
loc_parenthetical_pattern(min_indent),
|
||||||
tag_pattern(),
|
loc!(underscore_pattern()),
|
||||||
ident_pattern(),
|
loc_tag_pattern(min_indent),
|
||||||
record_destructure(min_indent),
|
loc!(ident_pattern()),
|
||||||
string_pattern(),
|
loc!(record_destructure(min_indent)),
|
||||||
int_pattern()
|
loc!(string_pattern()),
|
||||||
|
loc!(int_pattern())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn loc_parenthetical_pattern<'a>(min_indent: u16) -> impl Parser<'a, Located<Pattern<'a>>> {
|
||||||
|
between!(
|
||||||
|
char('('),
|
||||||
|
move |arena, state| loc_pattern(min_indent).parse(arena, state),
|
||||||
|
char(')')
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -796,7 +805,7 @@ fn underscore_pattern<'a>() -> impl Parser<'a, Pattern<'a>> {
|
||||||
|
|
||||||
fn record_destructure<'a>(min_indent: u16) -> impl Parser<'a, Pattern<'a>> {
|
fn record_destructure<'a>(min_indent: u16) -> impl Parser<'a, Pattern<'a>> {
|
||||||
then(
|
then(
|
||||||
record_without_update!(loc!(pattern(min_indent)), min_indent),
|
record_without_update!(loc_pattern(min_indent), min_indent),
|
||||||
move |arena, state, assigned_fields| {
|
move |arena, state, assigned_fields| {
|
||||||
let mut patterns = Vec::with_capacity_in(assigned_fields.len(), arena);
|
let mut patterns = Vec::with_capacity_in(assigned_fields.len(), arena);
|
||||||
for assigned_field in assigned_fields {
|
for assigned_field in assigned_fields {
|
||||||
|
@ -815,10 +824,29 @@ fn record_destructure<'a>(min_indent: u16) -> impl Parser<'a, Pattern<'a>> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tag_pattern<'a>() -> impl Parser<'a, Pattern<'a>> {
|
fn loc_tag_pattern<'a>(min_indent: u16) -> impl Parser<'a, Located<Pattern<'a>>> {
|
||||||
one_of!(
|
map_with_arena!(
|
||||||
map!(private_tag(), Pattern::PrivateTag),
|
and!(
|
||||||
map!(global_tag(), Pattern::GlobalTag)
|
loc!(one_of!(
|
||||||
|
map!(private_tag(), Pattern::PrivateTag),
|
||||||
|
map!(global_tag(), Pattern::GlobalTag)
|
||||||
|
)),
|
||||||
|
// This can optionally be an applied pattern, e.g. (Foo bar) instead of (Foo)
|
||||||
|
zero_or_more!(space1_before(loc_pattern(min_indent), min_indent))
|
||||||
|
),
|
||||||
|
|arena: &'a Bump,
|
||||||
|
(loc_tag, loc_args): (Located<Pattern<'a>>, Vec<'a, Located<Pattern<'a>>>)| {
|
||||||
|
if loc_args.is_empty() {
|
||||||
|
loc_tag
|
||||||
|
} else {
|
||||||
|
// TODO FIME this region doesn't cover the tag's
|
||||||
|
// arguments; need to add them to the region!
|
||||||
|
let region = loc_tag.region;
|
||||||
|
let value = Pattern::Apply(&*arena.alloc(loc_tag), loc_args.into_bump_slice());
|
||||||
|
|
||||||
|
Located { region, value }
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -868,7 +896,7 @@ pub fn case_branches<'a>(
|
||||||
// 2. Parse the other branches. Their indentation levels must be == the first branch's.
|
// 2. Parse the other branches. Their indentation levels must be == the first branch's.
|
||||||
|
|
||||||
let (mut loc_first_pattern, state) =
|
let (mut loc_first_pattern, state) =
|
||||||
space1_before(loc!(pattern(min_indent)), min_indent).parse(arena, state)?;
|
space1_before(loc_pattern(min_indent), min_indent).parse(arena, state)?;
|
||||||
let original_indent = state.indent_col;
|
let original_indent = state.indent_col;
|
||||||
let indented_more = original_indent + 1;
|
let indented_more = original_indent + 1;
|
||||||
let (spaces_before_arrow, state) = space0(min_indent).parse(arena, state)?;
|
let (spaces_before_arrow, state) = space0(min_indent).parse(arena, state)?;
|
||||||
|
@ -898,7 +926,7 @@ pub fn case_branches<'a>(
|
||||||
|
|
||||||
let branch_parser = and!(
|
let branch_parser = and!(
|
||||||
then(
|
then(
|
||||||
space1_around(loc!(pattern(min_indent)), min_indent),
|
space1_around(loc_pattern(min_indent), min_indent),
|
||||||
move |_arena, state, loc_pattern| {
|
move |_arena, state, loc_pattern| {
|
||||||
if state.indent_col == original_indent {
|
if state.indent_col == original_indent {
|
||||||
Ok((loc_pattern, state))
|
Ok((loc_pattern, state))
|
||||||
|
|
|
@ -208,6 +208,13 @@ fn write_flat_type(flat_type: FlatType, subs: &mut Subs, buf: &mut String, paren
|
||||||
EmptyTagUnion => buf.push_str(EMPTY_TAG_UNION),
|
EmptyTagUnion => buf.push_str(EMPTY_TAG_UNION),
|
||||||
Func(args, ret) => write_fn(args, ret, subs, buf, parens),
|
Func(args, ret) => write_fn(args, ret, subs, buf, parens),
|
||||||
Record(fields, ext_var) => {
|
Record(fields, ext_var) => {
|
||||||
|
use crate::unify::gather_fields;
|
||||||
|
use crate::unify::RecordStructure;
|
||||||
|
|
||||||
|
// If the `ext` has concrete fields (e.g. { foo : Int}{ bar : Bool }), merge them
|
||||||
|
let RecordStructure { fields, ext } = gather_fields(subs, fields, ext_var);
|
||||||
|
let ext_var = ext;
|
||||||
|
|
||||||
if fields.is_empty() {
|
if fields.is_empty() {
|
||||||
buf.push_str(EMPTY_RECORD)
|
buf.push_str(EMPTY_RECORD)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -16,9 +16,9 @@ struct Context {
|
||||||
second_desc: Descriptor,
|
second_desc: Descriptor,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RecordStructure {
|
pub struct RecordStructure {
|
||||||
fields: ImMap<RecordFieldLabel, Variable>,
|
pub fields: ImMap<RecordFieldLabel, Variable>,
|
||||||
ext: Variable,
|
pub ext: Variable,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TagUnionStructure {
|
struct TagUnionStructure {
|
||||||
|
@ -519,7 +519,7 @@ fn unify_flex(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gather_fields(
|
pub fn gather_fields(
|
||||||
subs: &mut Subs,
|
subs: &mut Subs,
|
||||||
fields: ImMap<RecordFieldLabel, Variable>,
|
fields: ImMap<RecordFieldLabel, Variable>,
|
||||||
var: Variable,
|
var: Variable,
|
||||||
|
|
|
@ -241,7 +241,7 @@ mod test_format {
|
||||||
expr_formats_same(indoc!(
|
expr_formats_same(indoc!(
|
||||||
r#"
|
r#"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
"" \""" ""\"
|
"" \""" ""\"
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -294,6 +294,24 @@ mod test_format {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn destructure_tag_closure() {
|
||||||
|
expr_formats_same(indoc!(
|
||||||
|
r#"
|
||||||
|
\Foo a -> Foo a
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn destructure_nested_tag_closure() {
|
||||||
|
expr_formats_same(indoc!(
|
||||||
|
r#"
|
||||||
|
\Foo (Bar a) -> Foo (Bar a)
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// DEFS
|
// DEFS
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1005,7 +1005,7 @@ mod test_infer {
|
||||||
{ user & year: "foo" }
|
{ user & year: "foo" }
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"{ year : Str }{ name : Str }",
|
"{ name : Str, year : Str }",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -641,7 +641,7 @@ mod test_parse {
|
||||||
assert_eq!(Ok(expected), actual);
|
assert_eq!(Ok(expected), actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
// VARIANT
|
// TAG
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn basic_global_tag() {
|
fn basic_global_tag() {
|
||||||
|
|
|
@ -899,7 +899,7 @@ mod test_infer_uniq {
|
||||||
{ user & year: "foo" }
|
{ user & year: "foo" }
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"Attr.Attr * { year : (Attr.Attr * Str) }{ name : (Attr.Attr * Str) }",
|
"Attr.Attr * { name : (Attr.Attr * Str), year : (Attr.Attr * Str) }",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue