be more specific about int/float precision

This commit is contained in:
Folkert 2020-12-31 22:46:29 +01:00
parent 81bfea53e2
commit bcf1c46afe
3 changed files with 82 additions and 22 deletions

View file

@ -304,7 +304,9 @@ macro_rules! assert_opt_evals_to {
let context = Context::create(); let context = Context::create();
let stdlib = roc_builtins::unique::uniq_stdlib(); // don't use uniqueness types any more
// let stdlib = roc_builtins::unique::uniq_stdlib();
let stdlib = roc_builtins::std::standard_stdlib();
let (main_fn_name, errors, lib) = let (main_fn_name, errors, lib) =
$crate::helpers::eval::helper(&arena, $src, stdlib, $leak, &context); $crate::helpers::eval::helper(&arena, $src, stdlib, $leak, &context);

View file

@ -1,6 +1,6 @@
use self::InProgressProc::*; use self::InProgressProc::*;
use crate::exhaustive::{Ctor, Guard, RenderAs, TagId}; use crate::exhaustive::{Ctor, Guard, RenderAs, TagId};
use crate::layout::{Builtin, ClosureLayout, Layout, LayoutCache, LayoutProblem}; use crate::layout::{Builtin, ClosureLayout, Layout, LayoutCache, LayoutProblem, TAG_SIZE};
use bumpalo::collections::Vec; use bumpalo::collections::Vec;
use bumpalo::Bump; use bumpalo::Bump;
use roc_collections::all::{default_hasher, MutMap, MutSet}; use roc_collections::all::{default_hasher, MutMap, MutSet};
@ -2739,7 +2739,7 @@ pub fn with_hole<'a>(
stmt = Stmt::Let( stmt = Stmt::Let(
tag_id_symbol, tag_id_symbol,
Expr::Literal(Literal::Int(tag_id as i64)), Expr::Literal(Literal::Int(tag_id as i64)),
Layout::Builtin(Builtin::Int64), Layout::Builtin(TAG_SIZE),
arena.alloc(stmt), arena.alloc(stmt),
); );
@ -4734,7 +4734,7 @@ fn store_pattern<'a>(
if write_tag { if write_tag {
// add an element for the tag discriminant // add an element for the tag discriminant
arg_layouts.push(Layout::Builtin(Builtin::Int64)); arg_layouts.push(Layout::Builtin(TAG_SIZE));
} }
for (_, layout) in arguments { for (_, layout) in arguments {
@ -6039,13 +6039,20 @@ pub fn num_argument_to_int_or_float(
match subs.get_without_compacting(var).content { match subs.get_without_compacting(var).content {
Content::FlexVar(_) if known_to_be_float => IntOrFloat::BinaryFloatType(FloatPrecision::F64), Content::FlexVar(_) if known_to_be_float => IntOrFloat::BinaryFloatType(FloatPrecision::F64),
Content::FlexVar(_) => IntOrFloat::SignedIntType(IntPrecision::I64), // We default (Num *) to I64 Content::FlexVar(_) => IntOrFloat::SignedIntType(IntPrecision::I64), // We default (Num *) to I64
Content::Alias(Symbol::NUM_INTEGER, args, _) => {
debug_assert!(args.len() == 1);
// Recurse on the second argument
num_argument_to_int_or_float(subs, args[0].1, false)
}
Content::Alias(Symbol::NUM_I128, _, _) Content::Alias(Symbol::NUM_I128, _, _)
| Content::Alias(Symbol::NUM_SIGNED128, _, _) | Content::Alias(Symbol::NUM_SIGNED128, _, _)
| Content::Alias(Symbol::NUM_AT_SIGNED128, _, _) => { | Content::Alias(Symbol::NUM_AT_SIGNED128, _, _) => {
IntOrFloat::SignedIntType(IntPrecision::I128) IntOrFloat::SignedIntType(IntPrecision::I128)
} }
Content::Alias(Symbol::NUM_INT, _, _) Content::Alias(Symbol::NUM_INT, _, _)// We default Integer to I64
| Content::Alias(Symbol::NUM_INTEGER, _, _) // We default Integer to I64
| Content::Alias(Symbol::NUM_I64, _, _) | Content::Alias(Symbol::NUM_I64, _, _)
| Content::Alias(Symbol::NUM_SIGNED64, _, _) | Content::Alias(Symbol::NUM_SIGNED64, _, _)
| Content::Alias(Symbol::NUM_AT_SIGNED64, _, _) => { | Content::Alias(Symbol::NUM_AT_SIGNED64, _, _) => {
@ -6097,8 +6104,13 @@ pub fn num_argument_to_int_or_float(
// Recurse on the second argument // Recurse on the second argument
num_argument_to_int_or_float(subs, attr_args[1], false) num_argument_to_int_or_float(subs, attr_args[1], false)
} }
Content::Alias(Symbol::NUM_FLOAT, _, _) Content::Alias(Symbol::NUM_FLOATINGPOINT, args, _) => {
| Content::Alias(Symbol::NUM_FLOATINGPOINT, _, _) // We default FloatingPoint to F64 debug_assert!(args.len() == 1);
// Recurse on the second argument
num_argument_to_int_or_float(subs, args[0].1, true)
}
Content::Alias(Symbol::NUM_FLOAT, _, _) // We default FloatingPoint to F64
| Content::Alias(Symbol::NUM_F64, _, _) | Content::Alias(Symbol::NUM_F64, _, _)
| Content::Alias(Symbol::NUM_BINARY64, _, _) | Content::Alias(Symbol::NUM_BINARY64, _, _)
| Content::Alias(Symbol::NUM_AT_BINARY64, _, _) => { | Content::Alias(Symbol::NUM_AT_BINARY64, _, _) => {

View file

@ -11,6 +11,7 @@ pub const MAX_ENUM_SIZE: usize = (std::mem::size_of::<u8>() * 8) as usize;
/// If a (Num *) gets translated to a Layout, this is the numeric type it defaults to. /// If a (Num *) gets translated to a Layout, this is the numeric type it defaults to.
const DEFAULT_NUM_BUILTIN: Builtin<'_> = Builtin::Int64; const DEFAULT_NUM_BUILTIN: Builtin<'_> = Builtin::Int64;
pub const TAG_SIZE: Builtin<'_> = Builtin::Int64;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum LayoutProblem { pub enum LayoutProblem {
@ -820,15 +821,15 @@ fn layout_from_flat_type<'a>(
} }
Symbol::NUM_I32 => { Symbol::NUM_I32 => {
debug_assert_eq!(args.len(), 0); debug_assert_eq!(args.len(), 0);
Ok(Layout::Builtin(Builtin::Int64)) Ok(Layout::Builtin(Builtin::Int32))
} }
Symbol::NUM_I16 => { Symbol::NUM_I16 => {
debug_assert_eq!(args.len(), 0); debug_assert_eq!(args.len(), 0);
Ok(Layout::Builtin(Builtin::Int64)) Ok(Layout::Builtin(Builtin::Int16))
} }
Symbol::NUM_I8 => { Symbol::NUM_I8 => {
debug_assert_eq!(args.len(), 0); debug_assert_eq!(args.len(), 0);
Ok(Layout::Builtin(Builtin::Int64)) Ok(Layout::Builtin(Builtin::Int8))
} }
// I think unsigned and signed use the same layout // I think unsigned and signed use the same layout
@ -842,15 +843,15 @@ fn layout_from_flat_type<'a>(
} }
Symbol::NUM_U32 => { Symbol::NUM_U32 => {
debug_assert_eq!(args.len(), 0); debug_assert_eq!(args.len(), 0);
Ok(Layout::Builtin(Builtin::Int64)) Ok(Layout::Builtin(Builtin::Int32))
} }
Symbol::NUM_U16 => { Symbol::NUM_U16 => {
debug_assert_eq!(args.len(), 0); debug_assert_eq!(args.len(), 0);
Ok(Layout::Builtin(Builtin::Int64)) Ok(Layout::Builtin(Builtin::Int16))
} }
Symbol::NUM_U8 => { Symbol::NUM_U8 => {
debug_assert_eq!(args.len(), 0); debug_assert_eq!(args.len(), 0);
Ok(Layout::Builtin(Builtin::Int64)) Ok(Layout::Builtin(Builtin::Int8))
} }
// Floats // Floats
@ -987,7 +988,7 @@ fn layout_from_flat_type<'a>(
let mut tag_layout = Vec::with_capacity_in(variables.len() + 1, arena); let mut tag_layout = Vec::with_capacity_in(variables.len() + 1, arena);
// store the discriminant // store the discriminant
tag_layout.push(Layout::Builtin(Builtin::Int64)); tag_layout.push(Layout::Builtin(TAG_SIZE));
for var in variables { for var in variables {
// TODO does this cause problems with mutually recursive unions? // TODO does this cause problems with mutually recursive unions?
@ -1218,7 +1219,7 @@ pub fn union_sorted_tags_help<'a>(
let mut arg_layouts = Vec::with_capacity_in(arguments.len() + 1, arena); let mut arg_layouts = Vec::with_capacity_in(arguments.len() + 1, arena);
// add the tag discriminant (size currently always hardcoded to i64) // add the tag discriminant (size currently always hardcoded to i64)
arg_layouts.push(Layout::Builtin(Builtin::Int64)); arg_layouts.push(Layout::Builtin(TAG_SIZE));
for var in arguments { for var in arguments {
match Layout::from_var(&mut env, var) { match Layout::from_var(&mut env, var) {
@ -1410,17 +1411,62 @@ fn unwrap_num_tag<'a>(subs: &Subs, var: Variable) -> Result<Layout<'a>, LayoutPr
Content::Alias(Symbol::NUM_INTEGER, args, _) => { Content::Alias(Symbol::NUM_INTEGER, args, _) => {
debug_assert!(args.len() == 1); debug_assert!(args.len() == 1);
// TODO: we probably need to match on the type of the arg let (_, precision_var) = args[0];
// and return the correct builtin ex: Builtin::{Int32, Int16}
let precision = subs.get_without_compacting(precision_var).content;
match precision {
Content::Alias(symbol, args, _) => {
debug_assert!(args.is_empty());
let builtin = match symbol {
Symbol::NUM_SIGNED128 => Builtin::Int128,
Symbol::NUM_SIGNED64 => Builtin::Int64,
Symbol::NUM_SIGNED32 => Builtin::Int32,
Symbol::NUM_SIGNED16 => Builtin::Int16,
Symbol::NUM_SIGNED8 => Builtin::Int8,
Symbol::NUM_UNSIGNED128 => Builtin::Int128,
Symbol::NUM_UNSIGNED64 => Builtin::Int64,
Symbol::NUM_UNSIGNED32 => Builtin::Int32,
Symbol::NUM_UNSIGNED16 => Builtin::Int16,
Symbol::NUM_UNSIGNED8 => Builtin::Int8,
_ => unreachable!("not a valid int variant: {:?} {:?}", symbol, args),
};
Ok(Layout::Builtin(builtin))
}
Content::FlexVar(_) => {
// default to i64
Ok(Layout::Builtin(Builtin::Int64)) Ok(Layout::Builtin(Builtin::Int64))
} }
_ => unreachable!("not a valid int variant: {:?}", precision),
}
}
Content::Alias(Symbol::NUM_FLOATINGPOINT, args, _) => { Content::Alias(Symbol::NUM_FLOATINGPOINT, args, _) => {
debug_assert!(args.len() == 1); debug_assert!(args.len() == 1);
// TODO: we probably need to match on the type of the arg let (_, precision_var) = args[0];
// and return the correct builtin ex: Builtin::Float32
let precision = subs.get_without_compacting(precision_var).content;
match precision {
Content::Alias(Symbol::NUM_BINARY32, args, _) => {
debug_assert!(args.is_empty());
Ok(Layout::Builtin(Builtin::Float32))
}
Content::Alias(Symbol::NUM_BINARY64, args, _) => {
debug_assert!(args.is_empty());
Ok(Layout::Builtin(Builtin::Float64)) Ok(Layout::Builtin(Builtin::Float64))
} }
Content::FlexVar(_) => {
// default to f64
Ok(Layout::Builtin(Builtin::Float64))
}
_ => unreachable!("not a valid float variant: {:?}", precision),
}
}
Content::FlexVar(_) | Content::RigidVar(_) => { Content::FlexVar(_) | Content::RigidVar(_) => {
// If this was still a (Num *) then default to compiling it to i64 // If this was still a (Num *) then default to compiling it to i64
Ok(Layout::Builtin(DEFAULT_NUM_BUILTIN)) Ok(Layout::Builtin(DEFAULT_NUM_BUILTIN))