mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
extract tags from the ext variable
turns out this is always needed. I also removed the explicit check for an empty tag union: there could still be tags in the ext even if the union itself seems empty. seems weird to optimize for the empty case because it'll be very rare in practice
This commit is contained in:
parent
e6e9676b70
commit
12a819e762
1 changed files with 77 additions and 89 deletions
|
@ -359,10 +359,7 @@ fn write_flat_type(
|
||||||
// Sort the fields so they always end up in the same order.
|
// Sort the fields so they always end up in the same order.
|
||||||
let mut sorted_fields = Vec::with_capacity(fields.len());
|
let mut sorted_fields = Vec::with_capacity(fields.len());
|
||||||
|
|
||||||
for (label, field_var) in fields {
|
sorted_fields.extend(fields);
|
||||||
sorted_fields.push((label, field_var));
|
|
||||||
}
|
|
||||||
|
|
||||||
sorted_fields.sort_by(|(a, _), (b, _)| a.cmp(b));
|
sorted_fields.sort_by(|(a, _), (b, _)| a.cmp(b));
|
||||||
|
|
||||||
let mut any_written_yet = false;
|
let mut any_written_yet = false;
|
||||||
|
@ -397,110 +394,101 @@ fn write_flat_type(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TagUnion(tags, ext_var) => {
|
TagUnion(tags, ext_var) => {
|
||||||
if tags.is_empty() {
|
let interns = &env.interns;
|
||||||
buf.push_str(EMPTY_TAG_UNION)
|
let home = env.home;
|
||||||
} else {
|
|
||||||
let interns = &env.interns;
|
|
||||||
let home = env.home;
|
|
||||||
|
|
||||||
buf.push_str("[ ");
|
buf.push_str("[ ");
|
||||||
|
|
||||||
// Sort the fields so they always end up in the same order.
|
// Sort the fields so they always end up in the same order.
|
||||||
let mut sorted_fields = Vec::with_capacity(tags.len());
|
let mut sorted_fields = Vec::with_capacity(tags.len());
|
||||||
|
|
||||||
for (label, vars) in tags {
|
for (label, vars) in tags {
|
||||||
sorted_fields.push((label.clone(), vars));
|
sorted_fields.push((label.clone(), vars));
|
||||||
}
|
|
||||||
|
|
||||||
sorted_fields.sort_by(|(a, _), (b, _)| {
|
|
||||||
a.clone()
|
|
||||||
.into_string(interns, home)
|
|
||||||
.cmp(&b.clone().into_string(&interns, home))
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut any_written_yet = false;
|
|
||||||
|
|
||||||
for (label, vars) in sorted_fields {
|
|
||||||
if any_written_yet {
|
|
||||||
buf.push_str(", ");
|
|
||||||
} else {
|
|
||||||
any_written_yet = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.push_str(&label.into_string(&interns, home));
|
|
||||||
|
|
||||||
for var in vars {
|
|
||||||
buf.push(' ');
|
|
||||||
write_content(env, subs.get(var).content, subs, buf, Parens::InTypeParam);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.push_str(" ]");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match subs.get(ext_var).content {
|
// If the `ext` contains tags, merge them into the list of tags.
|
||||||
Content::Structure(EmptyTagUnion) => {
|
// this can occur when inferring mutually recursive tags
|
||||||
// This is a closed record. We're done!
|
let ext_content = chase_ext_tag_union(subs, ext_var, &mut sorted_fields);
|
||||||
|
|
||||||
|
sorted_fields.sort_by(|(a, _), (b, _)| {
|
||||||
|
a.clone()
|
||||||
|
.into_string(interns, home)
|
||||||
|
.cmp(&b.clone().into_string(&interns, home))
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut any_written_yet = false;
|
||||||
|
|
||||||
|
for (label, vars) in sorted_fields {
|
||||||
|
if any_written_yet {
|
||||||
|
buf.push_str(", ");
|
||||||
|
} else {
|
||||||
|
any_written_yet = true;
|
||||||
}
|
}
|
||||||
content => {
|
|
||||||
// This is an open tag union, so print the variable
|
buf.push_str(&label.into_string(&interns, home));
|
||||||
// right after the ']'
|
|
||||||
//
|
for var in vars {
|
||||||
// e.g. the "*" at the end of `{ x: Int }*`
|
buf.push(' ');
|
||||||
// or the "r" at the end of `{ x: Int }r`
|
write_content(env, subs.get(var).content, subs, buf, Parens::InTypeParam);
|
||||||
write_content(env, content, subs, buf, parens)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buf.push_str(" ]");
|
||||||
|
|
||||||
|
if let Some(content) = ext_content {
|
||||||
|
// This is an open tag union, so print the variable
|
||||||
|
// right after the ']'
|
||||||
|
//
|
||||||
|
// e.g. the "*" at the end of `{ x: Int }*`
|
||||||
|
// or the "r" at the end of `{ x: Int }r`
|
||||||
|
write_content(env, content, subs, buf, parens)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||||
if tags.is_empty() {
|
let interns = &env.interns;
|
||||||
buf.push_str(EMPTY_TAG_UNION)
|
let home = env.home;
|
||||||
} else {
|
|
||||||
let interns = &env.interns;
|
|
||||||
let home = env.home;
|
|
||||||
|
|
||||||
buf.push_str("[ ");
|
buf.push_str("[ ");
|
||||||
|
|
||||||
// Sort the fields so they always end up in the same order.
|
// Sort the fields so they always end up in the same order.
|
||||||
let mut sorted_fields = Vec::with_capacity(tags.len());
|
let mut sorted_fields = Vec::with_capacity(tags.len());
|
||||||
|
|
||||||
for (label, vars) in tags {
|
for (label, vars) in tags {
|
||||||
sorted_fields.push((label.clone(), vars));
|
sorted_fields.push((label.clone(), vars));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the `ext` contains tags, merge them into the list of tags.
|
||||||
|
// this can occur when inferring mutually recursive tags
|
||||||
|
let ext_content = chase_ext_tag_union(subs, ext_var, &mut sorted_fields);
|
||||||
|
|
||||||
|
sorted_fields.sort_by(|(a, _), (b, _)| a.cmp(b));
|
||||||
|
|
||||||
|
let mut any_written_yet = false;
|
||||||
|
|
||||||
|
for (label, vars) in sorted_fields {
|
||||||
|
if any_written_yet {
|
||||||
|
buf.push_str(", ");
|
||||||
|
} else {
|
||||||
|
any_written_yet = true;
|
||||||
}
|
}
|
||||||
|
buf.push_str(&label.into_string(&interns, home));
|
||||||
|
|
||||||
// If the `ext` contains tags, merge them into the list of tags.
|
for var in vars {
|
||||||
// this can occur when inferring mutually recursive tags
|
buf.push(' ');
|
||||||
let ext_content = chase_ext_tag_union(subs, ext_var, &mut sorted_fields);
|
write_content(env, subs.get(var).content, subs, buf, Parens::InTypeParam);
|
||||||
|
|
||||||
sorted_fields.sort_by(|(a, _), (b, _)| a.cmp(b));
|
|
||||||
|
|
||||||
let mut any_written_yet = false;
|
|
||||||
|
|
||||||
for (label, vars) in sorted_fields {
|
|
||||||
if any_written_yet {
|
|
||||||
buf.push_str(", ");
|
|
||||||
} else {
|
|
||||||
any_written_yet = true;
|
|
||||||
}
|
|
||||||
buf.push_str(&label.into_string(&interns, home));
|
|
||||||
|
|
||||||
for var in vars {
|
|
||||||
buf.push(' ');
|
|
||||||
write_content(env, subs.get(var).content, subs, buf, Parens::InTypeParam);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buf.push_str(" ]");
|
buf.push_str(" ]");
|
||||||
|
|
||||||
if let Some(content) = ext_content {
|
if let Some(content) = ext_content {
|
||||||
// This is an open tag union, so print the variable
|
// This is an open tag union, so print the variable
|
||||||
// right after the ']'
|
// right after the ']'
|
||||||
//
|
//
|
||||||
// e.g. the "*" at the end of `{ x: Int }*`
|
// e.g. the "*" at the end of `{ x: Int }*`
|
||||||
// or the "r" at the end of `{ x: Int }r`
|
// or the "r" at the end of `{ x: Int }r`
|
||||||
write_content(env, content, subs, buf, parens)
|
write_content(env, content, subs, buf, parens)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.push_str(" as ");
|
buf.push_str(" as ");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue