mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 12:18:19 +00:00
Merge pull request #3535 from rtfeldman/bindgen-unit-result-bool
Bindgen Result, Bool, {}, and []
This commit is contained in:
commit
19436cc58a
2 changed files with 112 additions and 16 deletions
|
@ -255,8 +255,11 @@ fn add_type(target_info: TargetInfo, id: TypeId, types: &Types, impls: &mut Impl
|
|||
}
|
||||
}
|
||||
// These types don't need to be declared in Rust.
|
||||
RocType::Num(_)
|
||||
RocType::Unit
|
||||
| RocType::EmptyTagUnion
|
||||
| RocType::Num(_)
|
||||
| RocType::Bool
|
||||
| RocType::RocResult(_, _)
|
||||
| RocType::RocStr
|
||||
| RocType::RocDict(_, _)
|
||||
| RocType::RocSet(_)
|
||||
|
@ -609,7 +612,9 @@ pub struct {name} {{
|
|||
}
|
||||
|
||||
match payload_type {
|
||||
RocType::RocStr
|
||||
RocType::Unit
|
||||
| RocType::EmptyTagUnion
|
||||
| RocType::RocStr
|
||||
| RocType::Bool
|
||||
| RocType::Num(_)
|
||||
| RocType::RocList(_)
|
||||
|
@ -617,6 +622,7 @@ pub struct {name} {{
|
|||
| RocType::RocSet(_)
|
||||
| RocType::RocBox(_)
|
||||
| RocType::TagUnion(_)
|
||||
| RocType::RocResult(_, _)
|
||||
| RocType::RecursivePointer { .. } => {
|
||||
owned_ret_type = type_name(*payload_id, types);
|
||||
borrowed_ret_type = format!("&{}", owned_ret_type);
|
||||
|
@ -1100,7 +1106,9 @@ pub struct {name} {{
|
|||
};
|
||||
|
||||
let fields_str = match payload_type {
|
||||
RocType::RocStr
|
||||
RocType::Unit
|
||||
| RocType::EmptyTagUnion
|
||||
| RocType::RocStr
|
||||
| RocType::Bool
|
||||
| RocType::Num(_)
|
||||
| RocType::RocList(_)
|
||||
|
@ -1108,6 +1116,7 @@ pub struct {name} {{
|
|||
| RocType::RocSet(_)
|
||||
| RocType::RocBox(_)
|
||||
| RocType::TagUnion(_)
|
||||
| RocType::RocResult(_, _)
|
||||
| RocType::Struct { .. }
|
||||
| RocType::RecursivePointer { .. } => {
|
||||
format!(".field({deref_str}{actual_self}.{tag_name})")
|
||||
|
@ -1258,6 +1267,8 @@ fn add_struct<S: Display>(
|
|||
|
||||
fn type_name(id: TypeId, types: &Types) -> String {
|
||||
match types.get_type(id) {
|
||||
RocType::Unit => "()".to_string(),
|
||||
RocType::EmptyTagUnion => "std::convert::Infallible".to_string(),
|
||||
RocType::RocStr => "roc_std::RocStr".to_string(),
|
||||
RocType::Bool => "bool".to_string(),
|
||||
RocType::Num(RocNum::U8) => "u8".to_string(),
|
||||
|
@ -1282,6 +1293,13 @@ fn type_name(id: TypeId, types: &Types) -> String {
|
|||
RocType::RocSet(elem_id) => format!("roc_std::RocSet<{}>", type_name(*elem_id, types)),
|
||||
RocType::RocList(elem_id) => format!("roc_std::RocList<{}>", type_name(*elem_id, types)),
|
||||
RocType::RocBox(elem_id) => format!("roc_std::RocBox<{}>", type_name(*elem_id, types)),
|
||||
RocType::RocResult(ok_id, err_id) => {
|
||||
format!(
|
||||
"roc_std::RocResult<{}, {}>",
|
||||
type_name(*ok_id, types),
|
||||
type_name(*err_id, types)
|
||||
)
|
||||
}
|
||||
RocType::Struct { name, .. }
|
||||
| RocType::TagUnionPayload { name, .. }
|
||||
| RocType::TagUnion(RocTagUnion::NonRecursive { name, .. })
|
||||
|
@ -1398,13 +1416,16 @@ pub struct {name} {{
|
|||
let borrowed_ret;
|
||||
|
||||
match payload_type {
|
||||
RocType::RocStr
|
||||
RocType::Unit
|
||||
| RocType::EmptyTagUnion
|
||||
| RocType::RocStr
|
||||
| RocType::Bool
|
||||
| RocType::Num(_)
|
||||
| RocType::RocList(_)
|
||||
| RocType::RocDict(_, _)
|
||||
| RocType::RocSet(_)
|
||||
| RocType::RocBox(_)
|
||||
| RocType::RocResult(_, _)
|
||||
| RocType::TagUnion(_)
|
||||
| RocType::RecursivePointer { .. } => {
|
||||
owned_ret_type = type_name(non_null_payload, types);
|
||||
|
@ -1634,13 +1655,16 @@ pub struct {name} {{
|
|||
let extra_deref = if cannot_derive_copy { "*" } else { "" };
|
||||
|
||||
let fields_str = match payload_type {
|
||||
RocType::RocStr
|
||||
RocType::Unit
|
||||
| RocType::EmptyTagUnion
|
||||
| RocType::RocStr
|
||||
| RocType::Bool
|
||||
| RocType::Num(_)
|
||||
| RocType::RocList(_)
|
||||
| RocType::RocDict(_, _)
|
||||
| RocType::RocSet(_)
|
||||
| RocType::RocBox(_)
|
||||
| RocType::RocResult(_, _)
|
||||
| RocType::TagUnion(_)
|
||||
| RocType::RecursivePointer { .. } => {
|
||||
format!(
|
||||
|
@ -1863,9 +1887,12 @@ fn tag_union_struct_help<'a, I: Iterator<Item = &'a (L, TypeId)>, L: Display + P
|
|||
|
||||
fn cannot_derive_default(roc_type: &RocType, types: &Types) -> bool {
|
||||
match roc_type {
|
||||
RocType::TagUnion { .. } | RocType::RecursivePointer { .. } | RocType::Function(_, _) => {
|
||||
true
|
||||
}
|
||||
RocType::Unit
|
||||
| RocType::EmptyTagUnion
|
||||
| RocType::TagUnion { .. }
|
||||
| RocType::RocResult(_, _)
|
||||
| RocType::RecursivePointer { .. }
|
||||
| RocType::Function(_, _) => true,
|
||||
RocType::RocStr | RocType::Bool | RocType::Num(_) => false,
|
||||
RocType::RocList(id) | RocType::RocSet(id) | RocType::RocBox(id) => {
|
||||
cannot_derive_default(types.get_type(*id), types)
|
||||
|
@ -1886,7 +1913,9 @@ fn cannot_derive_default(roc_type: &RocType, types: &Types) -> bool {
|
|||
/// Useful when determining whether to derive Copy in a Rust type.
|
||||
fn cannot_derive_copy(roc_type: &RocType, types: &Types) -> bool {
|
||||
match roc_type {
|
||||
RocType::Bool
|
||||
RocType::Unit
|
||||
| RocType::EmptyTagUnion
|
||||
| RocType::Bool
|
||||
| RocType::Num(_)
|
||||
| RocType::TagUnion(RocTagUnion::Enumeration { .. })
|
||||
| RocType::Function(_, _) => false,
|
||||
|
@ -1907,6 +1936,10 @@ fn cannot_derive_copy(roc_type: &RocType, types: &Types) -> bool {
|
|||
.any(|id| cannot_derive_copy(types.get_type(*id), types))
|
||||
})
|
||||
}
|
||||
RocType::RocResult(ok_id, err_id) => {
|
||||
cannot_derive_copy(types.get_type(*ok_id), types)
|
||||
|| cannot_derive_copy(types.get_type(*err_id), types)
|
||||
}
|
||||
RocType::Struct { fields, .. } => fields
|
||||
.iter()
|
||||
.any(|(_, type_id)| cannot_derive_copy(types.get_type(*type_id), types)),
|
||||
|
@ -1931,13 +1964,19 @@ fn has_float_help(roc_type: &RocType, types: &Types, do_not_recurse: &[TypeId])
|
|||
I8 | U8 | I16 | U16 | I32 | U32 | I64 | U64 | I128 | U128 | Dec => false,
|
||||
}
|
||||
}
|
||||
RocType::RocStr
|
||||
RocType::Unit
|
||||
| RocType::EmptyTagUnion
|
||||
| RocType::RocStr
|
||||
| RocType::Bool
|
||||
| RocType::TagUnion(RocTagUnion::Enumeration { .. })
|
||||
| RocType::Function(_, _) => false,
|
||||
RocType::RocList(id) | RocType::RocSet(id) | RocType::RocBox(id) => {
|
||||
has_float_help(types.get_type(*id), types, do_not_recurse)
|
||||
}
|
||||
RocType::RocResult(ok_id, err_id) => {
|
||||
has_float_help(types.get_type(*ok_id), types, do_not_recurse)
|
||||
|| has_float_help(types.get_type(*err_id), types, do_not_recurse)
|
||||
}
|
||||
RocType::RocDict(key_id, val_id) => {
|
||||
has_float_help(types.get_type(*key_id), types, do_not_recurse)
|
||||
|| has_float_help(types.get_type(*val_id), types, do_not_recurse)
|
||||
|
|
|
@ -26,6 +26,9 @@ impl TypeId {
|
|||
/// have *some* TypeId value until we later in the process determine
|
||||
/// their real TypeId and can go back and fix them up.
|
||||
pub(crate) const PENDING: Self = Self(usize::MAX);
|
||||
|
||||
/// When adding, we check for overflow based on whether we've exceeded this.
|
||||
const MAX: Self = Self(Self::PENDING.0 - 1);
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -56,6 +59,8 @@ impl Types {
|
|||
pub fn add(&mut self, typ: RocType, layout: Layout<'_>) -> TypeId {
|
||||
let id = TypeId(self.types.len());
|
||||
|
||||
assert!(id.0 <= TypeId::MAX.0);
|
||||
|
||||
self.types.push(typ);
|
||||
self.sizes
|
||||
.push(layout.stack_size_without_alignment(self.target));
|
||||
|
@ -138,12 +143,14 @@ impl Types {
|
|||
pub enum RocType {
|
||||
RocStr,
|
||||
Bool,
|
||||
RocResult(TypeId, TypeId),
|
||||
Num(RocNum),
|
||||
RocList(TypeId),
|
||||
RocDict(TypeId, TypeId),
|
||||
RocSet(TypeId),
|
||||
RocBox(TypeId),
|
||||
TagUnion(RocTagUnion),
|
||||
EmptyTagUnion,
|
||||
Struct {
|
||||
name: String,
|
||||
fields: Vec<(String, TypeId)>,
|
||||
|
@ -157,6 +164,8 @@ pub enum RocType {
|
|||
/// and the TypeId is the TypeId of StrConsList itself.
|
||||
RecursivePointer(TypeId),
|
||||
Function(Vec<TypeId>, TypeId),
|
||||
/// A zero-sized type, such as an empty record or a single-tag union with no payload
|
||||
Unit,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
|
||||
|
@ -466,17 +475,65 @@ fn add_type_help<'a>(
|
|||
todo!()
|
||||
}
|
||||
Content::Structure(FlatType::Erroneous(_)) => todo!(),
|
||||
Content::Structure(FlatType::EmptyRecord) => todo!(),
|
||||
Content::Structure(FlatType::EmptyTagUnion) => {
|
||||
// This can happen when unwrapping a tag union; don't do anything.
|
||||
todo!()
|
||||
}
|
||||
Content::Alias(name, _, real_var, _) => {
|
||||
Content::Structure(FlatType::EmptyRecord) => types.add(RocType::Unit, layout),
|
||||
Content::Structure(FlatType::EmptyTagUnion) => types.add(RocType::EmptyTagUnion, layout),
|
||||
Content::Alias(name, alias_vars, real_var, _) => {
|
||||
if name.is_builtin() {
|
||||
match layout {
|
||||
Layout::Builtin(builtin) => {
|
||||
add_builtin_type(env, builtin, var, opt_name, types, layout)
|
||||
}
|
||||
Layout::Union(union_layout) if *name == Symbol::BOOL_BOOL => {
|
||||
if cfg!(debug_assertions) {
|
||||
match union_layout {
|
||||
UnionLayout::NonRecursive(tag_layouts) => {
|
||||
// Bool should always have exactly two tags: True and False
|
||||
debug_assert_eq!(tag_layouts.len(), 2);
|
||||
|
||||
// Both tags should have no payload
|
||||
debug_assert_eq!(tag_layouts[0].len(), 0);
|
||||
debug_assert_eq!(tag_layouts[1].len(), 0);
|
||||
}
|
||||
_ => debug_assert!(false),
|
||||
}
|
||||
}
|
||||
|
||||
types.add(RocType::Bool, layout)
|
||||
}
|
||||
Layout::Union(union_layout) if *name == Symbol::RESULT_RESULT => {
|
||||
match union_layout {
|
||||
UnionLayout::NonRecursive(tags) => {
|
||||
// Result should always have exactly two tags: Ok and Err
|
||||
debug_assert_eq!(tags.len(), 2);
|
||||
|
||||
let type_vars =
|
||||
env.subs.get_subs_slice(alias_vars.type_variables());
|
||||
|
||||
let ok_var = type_vars[0];
|
||||
let ok_layout =
|
||||
env.layout_cache.from_var(env.arena, ok_var, subs).unwrap();
|
||||
let ok_id = add_type_help(env, ok_layout, ok_var, None, types);
|
||||
|
||||
let err_var = type_vars[1];
|
||||
let err_layout =
|
||||
env.layout_cache.from_var(env.arena, err_var, subs).unwrap();
|
||||
let err_id = add_type_help(env, err_layout, err_var, None, types);
|
||||
|
||||
let type_id = types.add(RocType::RocResult(ok_id, err_id), layout);
|
||||
|
||||
types.depends(type_id, ok_id);
|
||||
types.depends(type_id, err_id);
|
||||
|
||||
type_id
|
||||
}
|
||||
UnionLayout::Recursive(_)
|
||||
| UnionLayout::NonNullableUnwrapped(_)
|
||||
| UnionLayout::NullableWrapped { .. }
|
||||
| UnionLayout::NullableUnwrapped { .. } => {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue