mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 16:21:11 +00:00
Check lower bounds for numeric literals, and permit 128-bit literals
This commit is contained in:
parent
a8b02831e5
commit
097c5afc73
16 changed files with 883 additions and 220 deletions
|
@ -8,7 +8,7 @@ use crate::layout::{
|
|||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
||||
use roc_can::expr::ClosureData;
|
||||
use roc_can::expr::{ClosureData, IntValue};
|
||||
use roc_collections::all::{default_hasher, BumpMap, BumpMapDefault, MutMap};
|
||||
use roc_module::ident::{ForeignSymbol, Lowercase, TagName};
|
||||
use roc_module::low_level::LowLevel;
|
||||
|
@ -1278,6 +1278,7 @@ impl ModifyRc {
|
|||
pub enum Literal<'a> {
|
||||
// Literals
|
||||
Int(i128),
|
||||
U128(u128),
|
||||
Float(f64),
|
||||
Decimal(RocDec),
|
||||
Str(&'a str),
|
||||
|
@ -1524,6 +1525,7 @@ impl<'a> Literal<'a> {
|
|||
|
||||
match self {
|
||||
Int(lit) => alloc.text(format!("{}i64", lit)),
|
||||
U128(lit) => alloc.text(format!("{}u128", lit)),
|
||||
Float(lit) => alloc.text(format!("{}f64", lit)),
|
||||
// TODO: Add proper Dec.to_str
|
||||
Decimal(lit) => alloc.text(format!("{}Dec", lit.0)),
|
||||
|
@ -3011,7 +3013,10 @@ fn try_make_literal<'a>(
|
|||
match can_expr {
|
||||
Int(_, precision, _, int, _bound) => {
|
||||
match num_argument_to_int_or_float(env.subs, env.target_info, *precision, false) {
|
||||
IntOrFloat::Int(_) => Some(Literal::Int(*int)),
|
||||
IntOrFloat::Int(_) => Some(match *int {
|
||||
IntValue::I128(n) => Literal::Int(n),
|
||||
IntValue::U128(n) => Literal::U128(n),
|
||||
}),
|
||||
_ => unreachable!("unexpected float precision for integer"),
|
||||
}
|
||||
}
|
||||
|
@ -3039,8 +3044,14 @@ fn try_make_literal<'a>(
|
|||
Num(var, num_str, num, _bound) => {
|
||||
// first figure out what kind of number this is
|
||||
match num_argument_to_int_or_float(env.subs, env.target_info, *var, false) {
|
||||
IntOrFloat::Int(_) => Some(Literal::Int((*num).into())),
|
||||
IntOrFloat::Float(_) => Some(Literal::Float(*num as f64)),
|
||||
IntOrFloat::Int(_) => Some(match *num {
|
||||
IntValue::I128(n) => Literal::Int(n),
|
||||
IntValue::U128(n) => Literal::U128(n),
|
||||
}),
|
||||
IntOrFloat::Float(_) => Some(match *num {
|
||||
IntValue::I128(n) => Literal::Float(n as f64),
|
||||
IntValue::U128(n) => Literal::Float(n as f64),
|
||||
}),
|
||||
IntOrFloat::DecimalFloatType => {
|
||||
let dec = match RocDec::from_str(num_str) {
|
||||
Some(d) => d,
|
||||
|
@ -3076,7 +3087,10 @@ pub fn with_hole<'a>(
|
|||
match num_argument_to_int_or_float(env.subs, env.target_info, precision, false) {
|
||||
IntOrFloat::Int(precision) => Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Int(int)),
|
||||
Expr::Literal(match int {
|
||||
IntValue::I128(n) => Literal::Int(n),
|
||||
IntValue::U128(n) => Literal::U128(n),
|
||||
}),
|
||||
Layout::Builtin(Builtin::Int(precision)),
|
||||
hole,
|
||||
),
|
||||
|
@ -3120,13 +3134,19 @@ pub fn with_hole<'a>(
|
|||
match num_argument_to_int_or_float(env.subs, env.target_info, var, false) {
|
||||
IntOrFloat::Int(precision) => Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Int(num.into())),
|
||||
Expr::Literal(match num {
|
||||
IntValue::I128(n) => Literal::Int(n),
|
||||
IntValue::U128(n) => Literal::U128(n),
|
||||
}),
|
||||
Layout::int_width(precision),
|
||||
hole,
|
||||
),
|
||||
IntOrFloat::Float(precision) => Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Float(num as f64)),
|
||||
Expr::Literal(match num {
|
||||
IntValue::I128(n) => Literal::Float(n as f64),
|
||||
IntValue::U128(n) => Literal::Float(n as f64),
|
||||
}),
|
||||
Layout::float_width(precision),
|
||||
hole,
|
||||
),
|
||||
|
@ -6211,6 +6231,7 @@ fn store_pattern_help<'a>(
|
|||
return StorePattern::NotProductive(stmt);
|
||||
}
|
||||
IntLiteral(_, _)
|
||||
| U128Literal(_)
|
||||
| FloatLiteral(_, _)
|
||||
| DecimalLiteral(_)
|
||||
| EnumLiteral { .. }
|
||||
|
@ -7583,6 +7604,7 @@ fn call_specialized_proc<'a>(
|
|||
pub enum Pattern<'a> {
|
||||
Identifier(Symbol),
|
||||
Underscore,
|
||||
U128Literal(u128),
|
||||
IntLiteral(i128, IntWidth),
|
||||
FloatLiteral(u64, FloatWidth),
|
||||
DecimalLiteral(RocDec),
|
||||
|
@ -7664,7 +7686,13 @@ fn from_can_pattern_help<'a>(
|
|||
Identifier(symbol) => Ok(Pattern::Identifier(*symbol)),
|
||||
IntLiteral(_, precision_var, _, int, _bound) => {
|
||||
match num_argument_to_int_or_float(env.subs, env.target_info, *precision_var, false) {
|
||||
IntOrFloat::Int(precision) => Ok(Pattern::IntLiteral(*int as i128, precision)),
|
||||
IntOrFloat::Int(precision) => {
|
||||
let int = match *int {
|
||||
IntValue::I128(n) => Pattern::IntLiteral(n, precision),
|
||||
IntValue::U128(n) => Pattern::U128Literal(n),
|
||||
};
|
||||
Ok(int)
|
||||
}
|
||||
other => {
|
||||
panic!(
|
||||
"Invalid precision for int pattern: {:?} has {:?}",
|
||||
|
@ -7706,8 +7734,18 @@ fn from_can_pattern_help<'a>(
|
|||
}
|
||||
NumLiteral(var, num_str, num, _bound) => {
|
||||
match num_argument_to_int_or_float(env.subs, env.target_info, *var, false) {
|
||||
IntOrFloat::Int(precision) => Ok(Pattern::IntLiteral(*num as i128, precision)),
|
||||
IntOrFloat::Float(precision) => Ok(Pattern::FloatLiteral(*num as u64, precision)),
|
||||
IntOrFloat::Int(precision) => Ok(match num {
|
||||
IntValue::I128(num) => Pattern::IntLiteral(*num, precision),
|
||||
IntValue::U128(num) => Pattern::U128Literal(*num),
|
||||
}),
|
||||
IntOrFloat::Float(precision) => {
|
||||
// TODO: this may be lossy
|
||||
let num = match *num {
|
||||
IntValue::I128(n) => f64::to_bits(n as f64),
|
||||
IntValue::U128(n) => f64::to_bits(n as f64),
|
||||
};
|
||||
Ok(Pattern::FloatLiteral(num, precision))
|
||||
}
|
||||
IntOrFloat::DecimalFloatType => {
|
||||
let dec = match RocDec::from_str(num_str) {
|
||||
Some(d) => d,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue