Numbers are opaques

This commit is contained in:
Ayaz Hafiz 2022-04-25 10:58:20 -04:00
parent 969d14dfe9
commit b6383f81ee
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
18 changed files with 684 additions and 1089 deletions

View file

@ -8640,9 +8640,9 @@ pub fn num_argument_to_int_or_float(
num_argument_to_int_or_float(subs, target_info, var, true)
}
Symbol::NUM_DECIMAL | Symbol::NUM_AT_DECIMAL => IntOrFloat::DecimalFloatType,
Symbol::NUM_DECIMAL => IntOrFloat::DecimalFloatType,
Symbol::NUM_NAT | Symbol::NUM_NATURAL | Symbol::NUM_AT_NATURAL => {
Symbol::NUM_NAT | Symbol::NUM_NATURAL => {
let int_width = match target_info.ptr_width() {
roc_target::PtrWidth::Bytes4 => IntWidth::U32,
roc_target::PtrWidth::Bytes8 => IntWidth::U64,

View file

@ -983,6 +983,16 @@ pub const fn round_up_to_alignment(width: u32, alignment: u32) -> u32 {
}
}
#[inline(always)]
pub fn is_unresolved_var(subs: &Subs, var: Variable) -> bool {
use Content::*;
let content = subs.get_content_without_compacting(var);
matches!(
content,
FlexVar(..) | RigidVar(..) | FlexAbleVar(..) | RigidAbleVar(..),
)
}
impl<'a> Layout<'a> {
pub const VOID: Self = Layout::Union(UnionLayout::NonRecursive(&[]));
pub const UNIT: Self = Layout::Struct {
@ -1015,12 +1025,24 @@ impl<'a> Layout<'a> {
}
match symbol {
Symbol::NUM_DECIMAL | Symbol::NUM_AT_DECIMAL => {
return Ok(Layout::Builtin(Builtin::Decimal))
Symbol::NUM_DECIMAL => return Ok(Layout::Builtin(Builtin::Decimal)),
Symbol::NUM_NAT | Symbol::NUM_NATURAL => {
return Ok(Layout::usize(env.target_info))
}
Symbol::NUM_NAT | Symbol::NUM_NATURAL | Symbol::NUM_AT_NATURAL => {
return Ok(Layout::usize(env.target_info))
Symbol::NUM_NUM | Symbol::NUM_INT | Symbol::NUM_INTEGER
if is_unresolved_var(env.subs, actual_var) =>
{
// default to i64
return Ok(Layout::i64());
}
Symbol::NUM_FLOAT | Symbol::NUM_FLOATINGPOINT
if is_unresolved_var(env.subs, actual_var) =>
{
// default to f64
return Ok(Layout::f64());
}
_ => Self::from_var(env, actual_var),
@ -1689,7 +1711,7 @@ fn layout_from_flat_type<'a>(
Ok(Layout::f32())
}
Symbol::NUM_NUM | Symbol::NUM_AT_NUM => {
Symbol::NUM_NUM => {
// Num.Num should only ever have 1 argument, e.g. Num.Num Int.Integer
debug_assert_eq!(args.len(), 1);
@ -2135,31 +2157,20 @@ fn union_sorted_tags_help_new<'a>(
// just one tag in the union (but with arguments) can be a struct
let mut layouts = Vec::with_capacity_in(tags_list.len(), env.arena);
// special-case NUM_AT_NUM: if its argument is a FlexVar, make it Int
match tag_name {
TagName::Private(Symbol::NUM_AT_NUM) => {
let var = arguments[0];
layouts.push(
unwrap_num_tag(env.subs, var, env.target_info).expect("invalid num layout"),
);
}
_ => {
for &var in arguments {
match Layout::from_var(env, var) {
Ok(layout) => {
layouts.push(layout);
}
Err(LayoutProblem::UnresolvedTypeVar(_)) => {
// If we encounter an unbound type var (e.g. `Ok *`)
// then it's zero-sized; In the future we may drop this argument
// completely, but for now we represent it with the empty tag union
layouts.push(Layout::VOID)
}
Err(LayoutProblem::Erroneous) => {
// An erroneous type var will code gen to a runtime
// error, so we don't need to store any data for it.
}
}
for &var in arguments {
match Layout::from_var(env, var) {
Ok(layout) => {
layouts.push(layout);
}
Err(LayoutProblem::UnresolvedTypeVar(_)) => {
// If we encounter an unbound type var (e.g. `Ok *`)
// then it's zero-sized; In the future we may drop this argument
// completely, but for now we represent it with the empty tag union
layouts.push(Layout::VOID)
}
Err(LayoutProblem::Erroneous) => {
// An erroneous type var will code gen to a runtime
// error, so we don't need to store any data for it.
}
}
}
@ -2341,37 +2352,26 @@ pub fn union_sorted_tags_help<'a>(
let mut layouts = Vec::with_capacity_in(tags_vec.len(), arena);
let mut contains_zero_sized = false;
// special-case NUM_AT_NUM: if its argument is a FlexVar, make it Int
match tag_name {
TagName::Private(Symbol::NUM_AT_NUM) => {
layouts.push(
unwrap_num_tag(subs, arguments[0], target_info)
.expect("invalid num layout"),
);
}
_ => {
for var in arguments {
match Layout::from_var(&mut env, var) {
Ok(layout) => {
// Drop any zero-sized arguments like {}
if !layout.is_dropped_because_empty() {
layouts.push(layout);
} else {
contains_zero_sized = true;
}
}
Err(LayoutProblem::UnresolvedTypeVar(_)) => {
// If we encounter an unbound type var (e.g. `Ok *`)
// then it's zero-sized; In the future we may drop this argument
// completely, but for now we represent it with the empty tag union
layouts.push(Layout::VOID)
}
Err(LayoutProblem::Erroneous) => {
// An erroneous type var will code gen to a runtime
// error, so we don't need to store any data for it.
}
for var in arguments {
match Layout::from_var(&mut env, var) {
Ok(layout) => {
// Drop any zero-sized arguments like {}
if !layout.is_dropped_because_empty() {
layouts.push(layout);
} else {
contains_zero_sized = true;
}
}
Err(LayoutProblem::UnresolvedTypeVar(_)) => {
// If we encounter an unbound type var (e.g. `Ok *`)
// then it's zero-sized; In the future we may drop this argument
// completely, but for now we represent it with the empty tag union
layouts.push(Layout::VOID)
}
Err(LayoutProblem::Erroneous) => {
// An erroneous type var will code gen to a runtime
// error, so we don't need to store any data for it.
}
}
}
@ -2529,24 +2529,20 @@ pub fn union_sorted_tags_help<'a>(
fn layout_from_newtype<'a>(env: &mut Env<'a, '_>, tags: &UnsortedUnionTags) -> Layout<'a> {
debug_assert!(tags.is_newtype_wrapper(env.subs));
let (tag_name, var) = tags.get_newtype(env.subs);
let (_tag_name, var) = tags.get_newtype(env.subs);
if tag_name == &TagName::Private(Symbol::NUM_AT_NUM) {
unwrap_num_tag(env.subs, var, env.target_info).expect("invalid Num argument")
} else {
match Layout::from_var(env, var) {
Ok(layout) => layout,
Err(LayoutProblem::UnresolvedTypeVar(_)) => {
// If we encounter an unbound type var (e.g. `Ok *`)
// then it's zero-sized; In the future we may drop this argument
// completely, but for now we represent it with the empty tag union
Layout::VOID
}
Err(LayoutProblem::Erroneous) => {
// An erroneous type var will code gen to a runtime
// error, so we don't need to store any data for it.
todo!()
}
match Layout::from_var(env, var) {
Ok(layout) => layout,
Err(LayoutProblem::UnresolvedTypeVar(_)) => {
// If we encounter an unbound type var (e.g. `Ok *`)
// then it's zero-sized; In the future we may drop this argument
// completely, but for now we represent it with the empty tag union
Layout::VOID
}
Err(LayoutProblem::Erroneous) => {
// An erroneous type var will code gen to a runtime
// error, so we don't need to store any data for it.
todo!()
}
}
}
@ -2560,76 +2556,65 @@ fn layout_from_tag_union<'a>(env: &mut Env<'a, '_>, tags: &UnsortedUnionTags) ->
let tags_vec = &tags.tags;
match tags_vec.get(0) {
Some((tag_name, arguments)) if *tag_name == &TagName::Private(Symbol::NUM_AT_NUM) => {
debug_assert_eq!(arguments.len(), 1);
let opt_rec_var = None;
let variant = union_sorted_tags_help_new(env, tags_vec, opt_rec_var);
let &var = arguments.iter().next().unwrap();
match variant {
Never => Layout::VOID,
Unit | UnitWithArguments => Layout::UNIT,
BoolUnion { .. } => Layout::bool(),
ByteUnion(_) => Layout::u8(),
Newtype {
arguments: field_layouts,
..
} => {
let answer1 = if field_layouts.len() == 1 {
field_layouts[0]
} else {
Layout::struct_no_name_order(field_layouts.into_bump_slice())
};
unwrap_num_tag(env.subs, var, env.target_info).expect("invalid Num argument")
answer1
}
_ => {
let opt_rec_var = None;
let variant = union_sorted_tags_help_new(env, tags_vec, opt_rec_var);
Wrapped(variant) => {
use WrappedVariant::*;
match variant {
Never => Layout::VOID,
Unit | UnitWithArguments => Layout::UNIT,
BoolUnion { .. } => Layout::bool(),
ByteUnion(_) => Layout::u8(),
Newtype {
arguments: field_layouts,
..
NonRecursive {
sorted_tag_layouts: tags,
} => {
let answer1 = if field_layouts.len() == 1 {
field_layouts[0]
} else {
Layout::struct_no_name_order(field_layouts.into_bump_slice())
};
let mut tag_layouts = Vec::with_capacity_in(tags.len(), env.arena);
tag_layouts.extend(tags.iter().map(|r| r.1));
answer1
Layout::Union(UnionLayout::NonRecursive(tag_layouts.into_bump_slice()))
}
Wrapped(variant) => {
use WrappedVariant::*;
match variant {
NonRecursive {
sorted_tag_layouts: tags,
} => {
let mut tag_layouts = Vec::with_capacity_in(tags.len(), env.arena);
tag_layouts.extend(tags.iter().map(|r| r.1));
Recursive {
sorted_tag_layouts: tags,
} => {
let mut tag_layouts = Vec::with_capacity_in(tags.len(), env.arena);
tag_layouts.extend(tags.iter().map(|r| r.1));
Layout::Union(UnionLayout::NonRecursive(tag_layouts.into_bump_slice()))
}
Recursive {
sorted_tag_layouts: tags,
} => {
let mut tag_layouts = Vec::with_capacity_in(tags.len(), env.arena);
tag_layouts.extend(tags.iter().map(|r| r.1));
debug_assert!(tag_layouts.len() > 1);
Layout::Union(UnionLayout::Recursive(tag_layouts.into_bump_slice()))
}
NullableWrapped {
nullable_id,
nullable_name: _,
sorted_tag_layouts: tags,
} => {
let mut tag_layouts = Vec::with_capacity_in(tags.len(), env.arena);
tag_layouts.extend(tags.iter().map(|r| r.1));
Layout::Union(UnionLayout::NullableWrapped {
nullable_id,
other_tags: tag_layouts.into_bump_slice(),
})
}
NullableUnwrapped { .. } => todo!(),
NonNullableUnwrapped { .. } => todo!(),
}
debug_assert!(tag_layouts.len() > 1);
Layout::Union(UnionLayout::Recursive(tag_layouts.into_bump_slice()))
}
NullableWrapped {
nullable_id,
nullable_name: _,
sorted_tag_layouts: tags,
} => {
let mut tag_layouts = Vec::with_capacity_in(tags.len(), env.arena);
tag_layouts.extend(tags.iter().map(|r| r.1));
Layout::Union(UnionLayout::NullableWrapped {
nullable_id,
other_tags: tag_layouts.into_bump_slice(),
})
}
NullableUnwrapped { .. } => todo!(),
NonNullableUnwrapped { .. } => todo!(),
}
}
}
@ -2727,6 +2712,8 @@ fn layout_from_num_content<'a>(
}
}
// TODO: removable?
#[allow(dead_code)]
fn unwrap_num_tag<'a>(
subs: &Subs,
var: Variable,

View file

@ -678,11 +678,9 @@ impl Layout {
}
match symbol {
Symbol::NUM_DECIMAL | Symbol::NUM_AT_DECIMAL => Ok(Layout::Decimal),
Symbol::NUM_DECIMAL => Ok(Layout::Decimal),
Symbol::NUM_NAT | Symbol::NUM_NATURAL | Symbol::NUM_AT_NATURAL => {
Ok(layouts.usize())
}
Symbol::NUM_NAT | Symbol::NUM_NATURAL => Ok(layouts.usize()),
_ => {
// at this point we throw away alias information