mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 13:59:08 +00:00
Fix glue generation for keywords
This commit is contained in:
parent
ace37cf613
commit
fa1f2f87ae
1 changed files with 37 additions and 10 deletions
|
@ -308,6 +308,8 @@ fn add_single_tag_struct(
|
||||||
impls: &mut IndexMap<Option<String>, IndexMap<String, Vec<TargetInfo>>>,
|
impls: &mut IndexMap<Option<String>, IndexMap<String, Vec<TargetInfo>>>,
|
||||||
target_info: TargetInfo,
|
target_info: TargetInfo,
|
||||||
) {
|
) {
|
||||||
|
let name = escape_kw(name.to_string());
|
||||||
|
|
||||||
// Store single-tag unions as structs rather than enums,
|
// Store single-tag unions as structs rather than enums,
|
||||||
// because they have only one alternative. However, still
|
// because they have only one alternative. However, still
|
||||||
// offer the usual tag union APIs.
|
// offer the usual tag union APIs.
|
||||||
|
@ -530,6 +532,8 @@ fn add_tag_union(
|
||||||
types: &Types,
|
types: &Types,
|
||||||
impls: &mut Impls,
|
impls: &mut Impls,
|
||||||
) {
|
) {
|
||||||
|
let name = escape_kw(name.to_string());
|
||||||
|
|
||||||
// We should never be attempting to generate glue for empty tag unions;
|
// We should never be attempting to generate glue for empty tag unions;
|
||||||
// RocType should not have let this happen.
|
// RocType should not have let this happen.
|
||||||
debug_assert_ne!(tags.len(), 0);
|
debug_assert_ne!(tags.len(), 0);
|
||||||
|
@ -537,7 +541,7 @@ fn add_tag_union(
|
||||||
let tag_names = tags.iter().map(|(name, _)| name).cloned().collect();
|
let tag_names = tags.iter().map(|(name, _)| name).cloned().collect();
|
||||||
let discriminant_name = if discriminant_size > 0 {
|
let discriminant_name = if discriminant_size > 0 {
|
||||||
add_discriminant(
|
add_discriminant(
|
||||||
name,
|
name.as_str(),
|
||||||
target_info,
|
target_info,
|
||||||
tag_names,
|
tag_names,
|
||||||
discriminant_size,
|
discriminant_size,
|
||||||
|
@ -585,7 +589,7 @@ pub struct {name} {{
|
||||||
}
|
}
|
||||||
Recursiveness::NonRecursive => {
|
Recursiveness::NonRecursive => {
|
||||||
pub_str = "pub ";
|
pub_str = "pub ";
|
||||||
decl_union_name = name;
|
decl_union_name = &name;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1100,7 +1104,7 @@ pub struct {name} {{
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Drop impl for the tag union
|
// The Drop impl for the tag union
|
||||||
{
|
if cannot_derive_copy(typ, types) {
|
||||||
let opt_impl = Some(format!("impl Drop for {name}"));
|
let opt_impl = Some(format!("impl Drop for {name}"));
|
||||||
let mut drop_payload = String::new();
|
let mut drop_payload = String::new();
|
||||||
|
|
||||||
|
@ -1584,6 +1588,7 @@ fn add_enumeration<I: ExactSizeIterator<Item = S>, S: AsRef<str> + Display>(
|
||||||
types: &Types,
|
types: &Types,
|
||||||
impls: &mut Impls,
|
impls: &mut Impls,
|
||||||
) {
|
) {
|
||||||
|
let name = escape_kw(name.to_string());
|
||||||
let derive = derive_str(typ, types, false);
|
let derive = derive_str(typ, types, false);
|
||||||
let repr_bits = tag_bytes * 8;
|
let repr_bits = tag_bytes * 8;
|
||||||
|
|
||||||
|
@ -1624,6 +1629,7 @@ fn add_struct<S: Display>(
|
||||||
impls: &mut Impls,
|
impls: &mut Impls,
|
||||||
is_tag_union_payload: bool,
|
is_tag_union_payload: bool,
|
||||||
) {
|
) {
|
||||||
|
let name = escape_kw(name.to_string());
|
||||||
let derive = derive_str(types.get_type(struct_id), types, true);
|
let derive = derive_str(types.get_type(struct_id), types, true);
|
||||||
let pub_str = if is_tag_union_payload { "" } else { "pub " };
|
let pub_str = if is_tag_union_payload { "" } else { "pub " };
|
||||||
let repr = if fields.len() == 1 {
|
let repr = if fields.len() == 1 {
|
||||||
|
@ -1641,7 +1647,7 @@ fn add_struct<S: Display>(
|
||||||
let label = if is_tag_union_payload {
|
let label = if is_tag_union_payload {
|
||||||
format!("f{label}")
|
format!("f{label}")
|
||||||
} else {
|
} else {
|
||||||
format!("{label}")
|
escape_kw(label.to_string())
|
||||||
};
|
};
|
||||||
|
|
||||||
writeln!(buf, "{INDENT}pub {label}: {type_str},",).unwrap();
|
writeln!(buf, "{INDENT}pub {label}: {type_str},",).unwrap();
|
||||||
|
@ -1695,9 +1701,9 @@ fn type_name(id: TypeId, types: &Types) -> String {
|
||||||
| RocType::TagUnion(RocTagUnion::NullableWrapped { name, .. })
|
| RocType::TagUnion(RocTagUnion::NullableWrapped { name, .. })
|
||||||
| RocType::TagUnion(RocTagUnion::NullableUnwrapped { name, .. })
|
| RocType::TagUnion(RocTagUnion::NullableUnwrapped { name, .. })
|
||||||
| RocType::TagUnion(RocTagUnion::NonNullableUnwrapped { name, .. })
|
| RocType::TagUnion(RocTagUnion::NonNullableUnwrapped { name, .. })
|
||||||
| RocType::TagUnion(RocTagUnion::SingleTagStruct { name, .. }) => name.clone(),
|
| RocType::TagUnion(RocTagUnion::SingleTagStruct { name, .. }) => escape_kw(name.clone()),
|
||||||
RocType::RecursivePointer(content) => type_name(*content, types),
|
RocType::RecursivePointer(content) => type_name(*content, types),
|
||||||
RocType::Function { name, .. } => name.clone(),
|
RocType::Function { name, .. } => escape_kw(name.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2181,7 +2187,7 @@ fn tag_union_struct_help<'a, I: Iterator<Item = &'a (L, TypeId)>, L: Display + P
|
||||||
// because they're numbers
|
// because they're numbers
|
||||||
format!("f{}", label)
|
format!("f{}", label)
|
||||||
} else {
|
} else {
|
||||||
format!("{}", label)
|
escape_kw(format!("{}", label))
|
||||||
};
|
};
|
||||||
|
|
||||||
ret_values.push(format!("payload.{label}"));
|
ret_values.push(format!("payload.{label}"));
|
||||||
|
@ -2214,9 +2220,7 @@ fn tag_union_struct_help<'a, I: Iterator<Item = &'a (L, TypeId)>, L: Display + P
|
||||||
|
|
||||||
// Tag union payload fields need "f" prefix
|
// Tag union payload fields need "f" prefix
|
||||||
// because they're numbers
|
// because they're numbers
|
||||||
let label = format!("f{}", label);
|
format!("{indents}f{label}: arg{index},")
|
||||||
|
|
||||||
format!("{indents}{label}: arg{index},")
|
|
||||||
})
|
})
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join("\n")
|
.join("\n")
|
||||||
|
@ -2424,3 +2428,26 @@ fn has_float_help(roc_type: &RocType, types: &Types, do_not_recurse: &[TypeId])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Based on https://doc.rust-lang.org/reference/keywords.html
|
||||||
|
const RESERVED_KEYWORDS: &[&'static str] = &[
|
||||||
|
"try", "abstract", "become", "box", "do", "final", "macro", "override", "priv", "typeof",
|
||||||
|
"unsized", "virtual", "yield", "async", "await", "dyn", "as", "break", "const", "continue",
|
||||||
|
"crate", "else", "enum", "extern", "false", "fn", "for", "if", "impl", "in", "let", "loop",
|
||||||
|
"match", "mod", "move", "mut", "pub", "ref", "return", "self", "Self", "static", "struct",
|
||||||
|
"super", "trait", "true", "type", "unsafe", "use", "where", "while",
|
||||||
|
];
|
||||||
|
|
||||||
|
/// Escape a Rust reserved keyword, if necessary.
|
||||||
|
fn escape_kw(input: String) -> String {
|
||||||
|
let is_reserved_keyword = RESERVED_KEYWORDS.contains(&input.as_str());
|
||||||
|
|
||||||
|
if is_reserved_keyword {
|
||||||
|
// Use a raw identifier for this, to prevent a syntax error due to using a reserved keyword.
|
||||||
|
// https://doc.rust-lang.org/rust-by-example/compatibility/raw_identifiers.html
|
||||||
|
// Another design would be to add an underscore after it; this is an experiment!
|
||||||
|
format!("r#{input}")
|
||||||
|
} else {
|
||||||
|
input
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue