mirror of
https://github.com/roc-lang/roc.git
synced 2025-12-23 08:48:03 +00:00
Merge pull request #8478 from roc-lang/num-conversions
Remaining number conversions
This commit is contained in:
commit
99e4ea7308
5 changed files with 1853 additions and 0 deletions
|
|
@ -454,7 +454,679 @@ fn replaceStrIsEmptyWithLowLevel(env: *ModuleEnv) !std.ArrayList(CIR.Def.Idx) {
|
|||
try low_level_map.put(ident, .i8_to_dec);
|
||||
}
|
||||
|
||||
// U16 conversion operations
|
||||
if (env.common.findIdent("Builtin.Num.U16.to_i8_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u16_to_i8_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U16.to_i8_try")) |ident| {
|
||||
try low_level_map.put(ident, .u16_to_i8_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U16.to_i16_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u16_to_i16_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U16.to_i16_try")) |ident| {
|
||||
try low_level_map.put(ident, .u16_to_i16_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U16.to_i32")) |ident| {
|
||||
try low_level_map.put(ident, .u16_to_i32);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U16.to_i64")) |ident| {
|
||||
try low_level_map.put(ident, .u16_to_i64);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U16.to_i128")) |ident| {
|
||||
try low_level_map.put(ident, .u16_to_i128);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U16.to_u8_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u16_to_u8_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U16.to_u8_try")) |ident| {
|
||||
try low_level_map.put(ident, .u16_to_u8_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U16.to_u32")) |ident| {
|
||||
try low_level_map.put(ident, .u16_to_u32);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U16.to_u64")) |ident| {
|
||||
try low_level_map.put(ident, .u16_to_u64);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U16.to_u128")) |ident| {
|
||||
try low_level_map.put(ident, .u16_to_u128);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U16.to_f32")) |ident| {
|
||||
try low_level_map.put(ident, .u16_to_f32);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U16.to_f64")) |ident| {
|
||||
try low_level_map.put(ident, .u16_to_f64);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U16.to_dec")) |ident| {
|
||||
try low_level_map.put(ident, .u16_to_dec);
|
||||
}
|
||||
|
||||
// I16 conversion operations
|
||||
if (env.common.findIdent("Builtin.Num.I16.to_i8_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i16_to_i8_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I16.to_i8_try")) |ident| {
|
||||
try low_level_map.put(ident, .i16_to_i8_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I16.to_i32")) |ident| {
|
||||
try low_level_map.put(ident, .i16_to_i32);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I16.to_i64")) |ident| {
|
||||
try low_level_map.put(ident, .i16_to_i64);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I16.to_i128")) |ident| {
|
||||
try low_level_map.put(ident, .i16_to_i128);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I16.to_u8_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i16_to_u8_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I16.to_u8_try")) |ident| {
|
||||
try low_level_map.put(ident, .i16_to_u8_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I16.to_u16_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i16_to_u16_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I16.to_u16_try")) |ident| {
|
||||
try low_level_map.put(ident, .i16_to_u16_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I16.to_u32_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i16_to_u32_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I16.to_u32_try")) |ident| {
|
||||
try low_level_map.put(ident, .i16_to_u32_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I16.to_u64_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i16_to_u64_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I16.to_u64_try")) |ident| {
|
||||
try low_level_map.put(ident, .i16_to_u64_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I16.to_u128_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i16_to_u128_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I16.to_u128_try")) |ident| {
|
||||
try low_level_map.put(ident, .i16_to_u128_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I16.to_f32")) |ident| {
|
||||
try low_level_map.put(ident, .i16_to_f32);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I16.to_f64")) |ident| {
|
||||
try low_level_map.put(ident, .i16_to_f64);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I16.to_dec")) |ident| {
|
||||
try low_level_map.put(ident, .i16_to_dec);
|
||||
}
|
||||
|
||||
// U32 conversion operations
|
||||
if (env.common.findIdent("Builtin.Num.U32.to_i8_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u32_to_i8_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U32.to_i8_try")) |ident| {
|
||||
try low_level_map.put(ident, .u32_to_i8_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U32.to_i16_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u32_to_i16_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U32.to_i16_try")) |ident| {
|
||||
try low_level_map.put(ident, .u32_to_i16_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U32.to_i32_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u32_to_i32_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U32.to_i32_try")) |ident| {
|
||||
try low_level_map.put(ident, .u32_to_i32_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U32.to_i64")) |ident| {
|
||||
try low_level_map.put(ident, .u32_to_i64);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U32.to_i128")) |ident| {
|
||||
try low_level_map.put(ident, .u32_to_i128);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U32.to_u8_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u32_to_u8_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U32.to_u8_try")) |ident| {
|
||||
try low_level_map.put(ident, .u32_to_u8_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U32.to_u16_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u32_to_u16_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U32.to_u16_try")) |ident| {
|
||||
try low_level_map.put(ident, .u32_to_u16_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U32.to_u64")) |ident| {
|
||||
try low_level_map.put(ident, .u32_to_u64);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U32.to_u128")) |ident| {
|
||||
try low_level_map.put(ident, .u32_to_u128);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U32.to_f32")) |ident| {
|
||||
try low_level_map.put(ident, .u32_to_f32);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U32.to_f64")) |ident| {
|
||||
try low_level_map.put(ident, .u32_to_f64);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U32.to_dec")) |ident| {
|
||||
try low_level_map.put(ident, .u32_to_dec);
|
||||
}
|
||||
|
||||
// I32 conversion operations
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_i8_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_i8_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_i8_try")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_i8_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_i16_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_i16_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_i16_try")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_i16_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_i64")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_i64);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_i128")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_i128);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_u8_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_u8_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_u8_try")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_u8_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_u16_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_u16_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_u16_try")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_u16_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_u32_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_u32_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_u32_try")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_u32_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_u64_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_u64_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_u64_try")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_u64_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_u128_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_u128_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_u128_try")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_u128_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_f32")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_f32);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_f64")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_f64);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I32.to_dec")) |ident| {
|
||||
try low_level_map.put(ident, .i32_to_dec);
|
||||
}
|
||||
|
||||
// U64 conversion operations
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_i8_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_i8_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_i8_try")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_i8_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_i16_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_i16_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_i16_try")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_i16_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_i32_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_i32_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_i32_try")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_i32_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_i64_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_i64_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_i64_try")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_i64_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_i128")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_i128);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_u8_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_u8_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_u8_try")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_u8_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_u16_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_u16_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_u16_try")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_u16_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_u32_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_u32_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_u32_try")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_u32_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_u128")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_u128);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_f32")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_f32);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_f64")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_f64);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U64.to_dec")) |ident| {
|
||||
try low_level_map.put(ident, .u64_to_dec);
|
||||
}
|
||||
|
||||
// I64 conversion operations
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_i8_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_i8_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_i8_try")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_i8_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_i16_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_i16_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_i16_try")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_i16_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_i32_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_i32_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_i32_try")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_i32_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_i128")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_i128);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_u8_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_u8_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_u8_try")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_u8_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_u16_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_u16_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_u16_try")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_u16_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_u32_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_u32_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_u32_try")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_u32_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_u64_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_u64_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_u64_try")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_u64_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_u128_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_u128_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_u128_try")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_u128_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_f32")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_f32);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_f64")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_f64);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I64.to_dec")) |ident| {
|
||||
try low_level_map.put(ident, .i64_to_dec);
|
||||
}
|
||||
|
||||
// U128 conversion operations
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_i8_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_i8_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_i8_try")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_i8_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_i16_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_i16_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_i16_try")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_i16_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_i32_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_i32_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_i32_try")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_i32_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_i64_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_i64_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_i64_try")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_i64_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_i128_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_i128_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_i128_try")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_i128_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_u8_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_u8_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_u8_try")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_u8_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_u16_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_u16_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_u16_try")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_u16_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_u32_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_u32_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_u32_try")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_u32_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_u64_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_u64_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_u64_try")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_u64_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_f32")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_f32);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.U128.to_f64")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_f64);
|
||||
}
|
||||
if (env.common.findIdent("u128_to_dec_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .u128_to_dec_try_unsafe);
|
||||
}
|
||||
|
||||
// I128 conversion operations
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_i8_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_i8_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_i8_try")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_i8_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_i16_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_i16_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_i16_try")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_i16_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_i32_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_i32_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_i32_try")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_i32_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_i64_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_i64_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_i64_try")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_i64_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_u8_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_u8_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_u8_try")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_u8_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_u16_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_u16_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_u16_try")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_u16_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_u32_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_u32_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_u32_try")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_u32_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_u64_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_u64_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_u64_try")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_u64_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_u128_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_u128_wrap);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_u128_try")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_u128_try);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_f32")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_f32);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.I128.to_f64")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_f64);
|
||||
}
|
||||
if (env.common.findIdent("i128_to_dec_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .i128_to_dec_try_unsafe);
|
||||
}
|
||||
|
||||
// F32 conversion operations
|
||||
if (env.common.findIdent("Builtin.Num.F32.to_i8_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_i8_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f32_to_i8_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_i8_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F32.to_i16_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_i16_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f32_to_i16_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_i16_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F32.to_i32_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_i32_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f32_to_i32_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_i32_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F32.to_i64_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_i64_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f32_to_i64_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_i64_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F32.to_i128_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_i128_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f32_to_i128_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_i128_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F32.to_u8_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_u8_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f32_to_u8_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_u8_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F32.to_u16_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_u16_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f32_to_u16_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_u16_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F32.to_u32_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_u32_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f32_to_u32_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_u32_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F32.to_u64_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_u64_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f32_to_u64_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_u64_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F32.to_u128_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_u128_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f32_to_u128_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_u128_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F32.to_f64")) |ident| {
|
||||
try low_level_map.put(ident, .f32_to_f64);
|
||||
}
|
||||
|
||||
// F64 conversion operations
|
||||
if (env.common.findIdent("Builtin.Num.F64.to_i8_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_i8_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f64_to_i8_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_i8_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F64.to_i16_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_i16_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f64_to_i16_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_i16_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F64.to_i32_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_i32_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f64_to_i32_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_i32_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F64.to_i64_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_i64_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f64_to_i64_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_i64_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F64.to_i128_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_i128_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f64_to_i128_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_i128_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F64.to_u8_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_u8_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f64_to_u8_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_u8_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F64.to_u16_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_u16_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f64_to_u16_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_u16_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F64.to_u32_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_u32_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f64_to_u32_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_u32_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F64.to_u64_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_u64_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f64_to_u64_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_u64_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F64.to_u128_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_u128_trunc);
|
||||
}
|
||||
if (env.common.findIdent("f64_to_u128_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_u128_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.F64.to_f32_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_f32_wrap);
|
||||
}
|
||||
if (env.common.findIdent("f64_to_f32_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .f64_to_f32_try_unsafe);
|
||||
}
|
||||
|
||||
// Dec conversion functions
|
||||
if (env.common.findIdent("Builtin.Num.Dec.to_i8_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_i8_trunc);
|
||||
}
|
||||
if (env.common.findIdent("dec_to_i8_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_i8_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.Dec.to_i16_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_i16_trunc);
|
||||
}
|
||||
if (env.common.findIdent("dec_to_i16_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_i16_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.Dec.to_i32_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_i32_trunc);
|
||||
}
|
||||
if (env.common.findIdent("dec_to_i32_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_i32_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.Dec.to_i64_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_i64_trunc);
|
||||
}
|
||||
if (env.common.findIdent("dec_to_i64_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_i64_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.Dec.to_i128_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_i128_trunc);
|
||||
}
|
||||
if (env.common.findIdent("dec_to_i128_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_i128_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.Dec.to_u8_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_u8_trunc);
|
||||
}
|
||||
if (env.common.findIdent("dec_to_u8_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_u8_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.Dec.to_u16_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_u16_trunc);
|
||||
}
|
||||
if (env.common.findIdent("dec_to_u16_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_u16_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.Dec.to_u32_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_u32_trunc);
|
||||
}
|
||||
if (env.common.findIdent("dec_to_u32_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_u32_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.Dec.to_u64_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_u64_trunc);
|
||||
}
|
||||
if (env.common.findIdent("dec_to_u64_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_u64_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.Dec.to_u128_trunc")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_u128_trunc);
|
||||
}
|
||||
if (env.common.findIdent("dec_to_u128_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_u128_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.Dec.to_f32_wrap")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_f32_wrap);
|
||||
}
|
||||
if (env.common.findIdent("dec_to_f32_try_unsafe")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_f32_try_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Num.Dec.to_f64")) |ident| {
|
||||
try low_level_map.put(ident, .dec_to_f64);
|
||||
}
|
||||
|
||||
// Iterate through all defs and replace matching anno-only defs with low-level implementations
|
||||
// NOTE: We copy def indices to a separate list first, because operations inside the loop
|
||||
// may reallocate extra_data, which would invalidate any slice taken from it.
|
||||
const all_defs_slice = env.store.sliceDefs(env.all_defs);
|
||||
var def_indices = std.ArrayList(CIR.Def.Idx).empty;
|
||||
defer def_indices.deinit(gpa);
|
||||
|
|
|
|||
|
|
@ -294,6 +294,27 @@ Builtin :: [].{
|
|||
|
||||
from_int_digits : List(U8) -> Try(U16, [OutOfRange])
|
||||
from_numeral : Numeral -> Try(U16, [InvalidNumeral(Str)])
|
||||
|
||||
# Conversions to signed integers
|
||||
to_i8_wrap : U16 -> I8
|
||||
to_i8_try : U16 -> Try(I8, [OutOfRange])
|
||||
to_i16_wrap : U16 -> I16
|
||||
to_i16_try : U16 -> Try(I16, [OutOfRange])
|
||||
to_i32 : U16 -> I32
|
||||
to_i64 : U16 -> I64
|
||||
to_i128 : U16 -> I128
|
||||
|
||||
# Conversions to unsigned integers
|
||||
to_u8_wrap : U16 -> U8
|
||||
to_u8_try : U16 -> Try(U8, [OutOfRange])
|
||||
to_u32 : U16 -> U32
|
||||
to_u64 : U16 -> U64
|
||||
to_u128 : U16 -> U128
|
||||
|
||||
# Conversions to floating point (all safe)
|
||||
to_f32 : U16 -> F32
|
||||
to_f64 : U16 -> F64
|
||||
to_dec : U16 -> Dec
|
||||
}
|
||||
|
||||
I16 :: [].{
|
||||
|
|
@ -317,6 +338,30 @@ Builtin :: [].{
|
|||
|
||||
from_int_digits : List(U8) -> Try(I16, [OutOfRange])
|
||||
from_numeral : Numeral -> Try(I16, [InvalidNumeral(Str)])
|
||||
|
||||
# Conversions to signed integers
|
||||
to_i8_wrap : I16 -> I8
|
||||
to_i8_try : I16 -> Try(I8, [OutOfRange])
|
||||
to_i32 : I16 -> I32
|
||||
to_i64 : I16 -> I64
|
||||
to_i128 : I16 -> I128
|
||||
|
||||
# Conversions to unsigned integers (all lossy for negative values)
|
||||
to_u8_wrap : I16 -> U8
|
||||
to_u8_try : I16 -> Try(U8, [OutOfRange])
|
||||
to_u16_wrap : I16 -> U16
|
||||
to_u16_try : I16 -> Try(U16, [OutOfRange])
|
||||
to_u32_wrap : I16 -> U32
|
||||
to_u32_try : I16 -> Try(U32, [OutOfRange])
|
||||
to_u64_wrap : I16 -> U64
|
||||
to_u64_try : I16 -> Try(U64, [OutOfRange])
|
||||
to_u128_wrap : I16 -> U128
|
||||
to_u128_try : I16 -> Try(U128, [OutOfRange])
|
||||
|
||||
# Conversions to floating point (all safe)
|
||||
to_f32 : I16 -> F32
|
||||
to_f64 : I16 -> F64
|
||||
to_dec : I16 -> Dec
|
||||
}
|
||||
|
||||
U32 :: [].{
|
||||
|
|
@ -337,6 +382,29 @@ Builtin :: [].{
|
|||
|
||||
from_int_digits : List(U8) -> Try(U32, [OutOfRange])
|
||||
from_numeral : Numeral -> Try(U32, [InvalidNumeral(Str)])
|
||||
|
||||
# Conversions to signed integers
|
||||
to_i8_wrap : U32 -> I8
|
||||
to_i8_try : U32 -> Try(I8, [OutOfRange])
|
||||
to_i16_wrap : U32 -> I16
|
||||
to_i16_try : U32 -> Try(I16, [OutOfRange])
|
||||
to_i32_wrap : U32 -> I32
|
||||
to_i32_try : U32 -> Try(I32, [OutOfRange])
|
||||
to_i64 : U32 -> I64
|
||||
to_i128 : U32 -> I128
|
||||
|
||||
# Conversions to unsigned integers
|
||||
to_u8_wrap : U32 -> U8
|
||||
to_u8_try : U32 -> Try(U8, [OutOfRange])
|
||||
to_u16_wrap : U32 -> U16
|
||||
to_u16_try : U32 -> Try(U16, [OutOfRange])
|
||||
to_u64 : U32 -> U64
|
||||
to_u128 : U32 -> U128
|
||||
|
||||
# Conversions to floating point (all safe)
|
||||
to_f32 : U32 -> F32
|
||||
to_f64 : U32 -> F64
|
||||
to_dec : U32 -> Dec
|
||||
}
|
||||
|
||||
I32 :: [].{
|
||||
|
|
@ -360,6 +428,31 @@ Builtin :: [].{
|
|||
|
||||
from_int_digits : List(U8) -> Try(I32, [OutOfRange])
|
||||
from_numeral : Numeral -> Try(I32, [InvalidNumeral(Str)])
|
||||
|
||||
# Conversions to signed integers
|
||||
to_i8_wrap : I32 -> I8
|
||||
to_i8_try : I32 -> Try(I8, [OutOfRange])
|
||||
to_i16_wrap : I32 -> I16
|
||||
to_i16_try : I32 -> Try(I16, [OutOfRange])
|
||||
to_i64 : I32 -> I64
|
||||
to_i128 : I32 -> I128
|
||||
|
||||
# Conversions to unsigned integers (all lossy for negative values)
|
||||
to_u8_wrap : I32 -> U8
|
||||
to_u8_try : I32 -> Try(U8, [OutOfRange])
|
||||
to_u16_wrap : I32 -> U16
|
||||
to_u16_try : I32 -> Try(U16, [OutOfRange])
|
||||
to_u32_wrap : I32 -> U32
|
||||
to_u32_try : I32 -> Try(U32, [OutOfRange])
|
||||
to_u64_wrap : I32 -> U64
|
||||
to_u64_try : I32 -> Try(U64, [OutOfRange])
|
||||
to_u128_wrap : I32 -> U128
|
||||
to_u128_try : I32 -> Try(U128, [OutOfRange])
|
||||
|
||||
# Conversions to floating point (all safe)
|
||||
to_f32 : I32 -> F32
|
||||
to_f64 : I32 -> F64
|
||||
to_dec : I32 -> Dec
|
||||
}
|
||||
|
||||
U64 :: [].{
|
||||
|
|
@ -380,6 +473,31 @@ Builtin :: [].{
|
|||
|
||||
from_int_digits : List(U8) -> Try(U64, [OutOfRange])
|
||||
from_numeral : Numeral -> Try(U64, [InvalidNumeral(Str)])
|
||||
|
||||
# Conversions to signed integers
|
||||
to_i8_wrap : U64 -> I8
|
||||
to_i8_try : U64 -> Try(I8, [OutOfRange])
|
||||
to_i16_wrap : U64 -> I16
|
||||
to_i16_try : U64 -> Try(I16, [OutOfRange])
|
||||
to_i32_wrap : U64 -> I32
|
||||
to_i32_try : U64 -> Try(I32, [OutOfRange])
|
||||
to_i64_wrap : U64 -> I64
|
||||
to_i64_try : U64 -> Try(I64, [OutOfRange])
|
||||
to_i128 : U64 -> I128
|
||||
|
||||
# Conversions to unsigned integers
|
||||
to_u8_wrap : U64 -> U8
|
||||
to_u8_try : U64 -> Try(U8, [OutOfRange])
|
||||
to_u16_wrap : U64 -> U16
|
||||
to_u16_try : U64 -> Try(U16, [OutOfRange])
|
||||
to_u32_wrap : U64 -> U32
|
||||
to_u32_try : U64 -> Try(U32, [OutOfRange])
|
||||
to_u128 : U64 -> U128
|
||||
|
||||
# Conversions to floating point (all safe)
|
||||
to_f32 : U64 -> F32
|
||||
to_f64 : U64 -> F64
|
||||
to_dec : U64 -> Dec
|
||||
}
|
||||
|
||||
I64 :: [].{
|
||||
|
|
@ -403,6 +521,32 @@ Builtin :: [].{
|
|||
|
||||
from_int_digits : List(U8) -> Try(I64, [OutOfRange])
|
||||
from_numeral : Numeral -> Try(I64, [InvalidNumeral(Str)])
|
||||
|
||||
# Conversions to signed integers
|
||||
to_i8_wrap : I64 -> I8
|
||||
to_i8_try : I64 -> Try(I8, [OutOfRange])
|
||||
to_i16_wrap : I64 -> I16
|
||||
to_i16_try : I64 -> Try(I16, [OutOfRange])
|
||||
to_i32_wrap : I64 -> I32
|
||||
to_i32_try : I64 -> Try(I32, [OutOfRange])
|
||||
to_i128 : I64 -> I128
|
||||
|
||||
# Conversions to unsigned integers (all lossy for negative values)
|
||||
to_u8_wrap : I64 -> U8
|
||||
to_u8_try : I64 -> Try(U8, [OutOfRange])
|
||||
to_u16_wrap : I64 -> U16
|
||||
to_u16_try : I64 -> Try(U16, [OutOfRange])
|
||||
to_u32_wrap : I64 -> U32
|
||||
to_u32_try : I64 -> Try(U32, [OutOfRange])
|
||||
to_u64_wrap : I64 -> U64
|
||||
to_u64_try : I64 -> Try(U64, [OutOfRange])
|
||||
to_u128_wrap : I64 -> U128
|
||||
to_u128_try : I64 -> Try(U128, [OutOfRange])
|
||||
|
||||
# Conversions to floating point (all safe)
|
||||
to_f32 : I64 -> F32
|
||||
to_f64 : I64 -> F64
|
||||
to_dec : I64 -> Dec
|
||||
}
|
||||
|
||||
U128 :: [].{
|
||||
|
|
@ -423,6 +567,35 @@ Builtin :: [].{
|
|||
|
||||
from_int_digits : List(U8) -> Try(U128, [OutOfRange])
|
||||
from_numeral : Numeral -> Try(U128, [InvalidNumeral(Str)])
|
||||
|
||||
# Conversions to signed integers
|
||||
to_i8_wrap : U128 -> I8
|
||||
to_i8_try : U128 -> Try(I8, [OutOfRange])
|
||||
to_i16_wrap : U128 -> I16
|
||||
to_i16_try : U128 -> Try(I16, [OutOfRange])
|
||||
to_i32_wrap : U128 -> I32
|
||||
to_i32_try : U128 -> Try(I32, [OutOfRange])
|
||||
to_i64_wrap : U128 -> I64
|
||||
to_i64_try : U128 -> Try(I64, [OutOfRange])
|
||||
to_i128_wrap : U128 -> I128
|
||||
to_i128_try : U128 -> Try(I128, [OutOfRange])
|
||||
|
||||
# Conversions to unsigned integers
|
||||
to_u8_wrap : U128 -> U8
|
||||
to_u8_try : U128 -> Try(U8, [OutOfRange])
|
||||
to_u16_wrap : U128 -> U16
|
||||
to_u16_try : U128 -> Try(U16, [OutOfRange])
|
||||
to_u32_wrap : U128 -> U32
|
||||
to_u32_try : U128 -> Try(U32, [OutOfRange])
|
||||
to_u64_wrap : U128 -> U64
|
||||
to_u64_try : U128 -> Try(U64, [OutOfRange])
|
||||
|
||||
# Conversions to floating point (all safe)
|
||||
to_f32 : U128 -> F32
|
||||
to_f64 : U128 -> F64
|
||||
|
||||
# Conversion to Dec (can overflow)
|
||||
to_dec_try : U128 -> Try(Dec, [OutOfRange])
|
||||
}
|
||||
|
||||
I128 :: [].{
|
||||
|
|
@ -446,6 +619,35 @@ Builtin :: [].{
|
|||
|
||||
from_int_digits : List(U8) -> Try(I128, [OutOfRange])
|
||||
from_numeral : Numeral -> Try(I128, [InvalidNumeral(Str)])
|
||||
|
||||
# Conversions to signed integers
|
||||
to_i8_wrap : I128 -> I8
|
||||
to_i8_try : I128 -> Try(I8, [OutOfRange])
|
||||
to_i16_wrap : I128 -> I16
|
||||
to_i16_try : I128 -> Try(I16, [OutOfRange])
|
||||
to_i32_wrap : I128 -> I32
|
||||
to_i32_try : I128 -> Try(I32, [OutOfRange])
|
||||
to_i64_wrap : I128 -> I64
|
||||
to_i64_try : I128 -> Try(I64, [OutOfRange])
|
||||
|
||||
# Conversions to unsigned integers (all lossy for negative values)
|
||||
to_u8_wrap : I128 -> U8
|
||||
to_u8_try : I128 -> Try(U8, [OutOfRange])
|
||||
to_u16_wrap : I128 -> U16
|
||||
to_u16_try : I128 -> Try(U16, [OutOfRange])
|
||||
to_u32_wrap : I128 -> U32
|
||||
to_u32_try : I128 -> Try(U32, [OutOfRange])
|
||||
to_u64_wrap : I128 -> U64
|
||||
to_u64_try : I128 -> Try(U64, [OutOfRange])
|
||||
to_u128_wrap : I128 -> U128
|
||||
to_u128_try : I128 -> Try(U128, [OutOfRange])
|
||||
|
||||
# Conversions to floating point (all safe)
|
||||
to_f32 : I128 -> F32
|
||||
to_f64 : I128 -> F64
|
||||
|
||||
# Conversion to Dec (can overflow)
|
||||
to_dec_try : I128 -> Try(Dec, [OutOfRange])
|
||||
}
|
||||
|
||||
Dec :: [].{
|
||||
|
|
@ -470,6 +672,35 @@ Builtin :: [].{
|
|||
from_int_digits : List(U8) -> Try(Dec, [OutOfRange])
|
||||
from_dec_digits : (List(U8), List(U8)) -> Try(Dec, [OutOfRange])
|
||||
from_numeral : Numeral -> Try(Dec, [InvalidNumeral(Str)])
|
||||
|
||||
# Conversions to signed integers (all lossy - truncates fractional part)
|
||||
to_i8_wrap : Dec -> I8
|
||||
to_i8_try : Dec -> Try(I8, [OutOfRange])
|
||||
to_i16_wrap : Dec -> I16
|
||||
to_i16_try : Dec -> Try(I16, [OutOfRange])
|
||||
to_i32_wrap : Dec -> I32
|
||||
to_i32_try : Dec -> Try(I32, [OutOfRange])
|
||||
to_i64_wrap : Dec -> I64
|
||||
to_i64_try : Dec -> Try(I64, [OutOfRange])
|
||||
to_i128_wrap : Dec -> I128
|
||||
to_i128_try : Dec -> Try(I128, [OutOfRange])
|
||||
|
||||
# Conversions to unsigned integers (all lossy - truncates fractional part)
|
||||
to_u8_wrap : Dec -> U8
|
||||
to_u8_try : Dec -> Try(U8, [OutOfRange])
|
||||
to_u16_wrap : Dec -> U16
|
||||
to_u16_try : Dec -> Try(U16, [OutOfRange])
|
||||
to_u32_wrap : Dec -> U32
|
||||
to_u32_try : Dec -> Try(U32, [OutOfRange])
|
||||
to_u64_wrap : Dec -> U64
|
||||
to_u64_try : Dec -> Try(U64, [OutOfRange])
|
||||
to_u128_wrap : Dec -> U128
|
||||
to_u128_try : Dec -> Try(U128, [OutOfRange])
|
||||
|
||||
# Conversions to floating point (lossy - Dec has more precision)
|
||||
to_f32_wrap : Dec -> F32
|
||||
to_f32_try : Dec -> Try(F32, [OutOfRange])
|
||||
to_f64 : Dec -> F64
|
||||
}
|
||||
|
||||
F32 :: [].{
|
||||
|
|
@ -493,6 +724,33 @@ Builtin :: [].{
|
|||
from_int_digits : List(U8) -> Try(F32, [OutOfRange])
|
||||
from_dec_digits : (List(U8), List(U8)) -> Try(F32, [OutOfRange])
|
||||
from_numeral : Numeral -> Try(F32, [InvalidNumeral(Str)])
|
||||
|
||||
# Conversions to signed integers (all lossy - truncation + range check)
|
||||
to_i8_wrap : F32 -> I8
|
||||
to_i8_try : F32 -> Try(I8, [OutOfRange])
|
||||
to_i16_wrap : F32 -> I16
|
||||
to_i16_try : F32 -> Try(I16, [OutOfRange])
|
||||
to_i32_wrap : F32 -> I32
|
||||
to_i32_try : F32 -> Try(I32, [OutOfRange])
|
||||
to_i64_wrap : F32 -> I64
|
||||
to_i64_try : F32 -> Try(I64, [OutOfRange])
|
||||
to_i128_wrap : F32 -> I128
|
||||
to_i128_try : F32 -> Try(I128, [OutOfRange])
|
||||
|
||||
# Conversions to unsigned integers (all lossy - truncation + range check)
|
||||
to_u8_wrap : F32 -> U8
|
||||
to_u8_try : F32 -> Try(U8, [OutOfRange])
|
||||
to_u16_wrap : F32 -> U16
|
||||
to_u16_try : F32 -> Try(U16, [OutOfRange])
|
||||
to_u32_wrap : F32 -> U32
|
||||
to_u32_try : F32 -> Try(U32, [OutOfRange])
|
||||
to_u64_wrap : F32 -> U64
|
||||
to_u64_try : F32 -> Try(U64, [OutOfRange])
|
||||
to_u128_wrap : F32 -> U128
|
||||
to_u128_try : F32 -> Try(U128, [OutOfRange])
|
||||
|
||||
# Conversion to F64 (safe widening)
|
||||
to_f64 : F32 -> F64
|
||||
}
|
||||
|
||||
F64 :: [].{
|
||||
|
|
@ -516,6 +774,39 @@ Builtin :: [].{
|
|||
from_int_digits : List(U8) -> Try(F64, [OutOfRange])
|
||||
from_dec_digits : (List(U8), List(U8)) -> Try(F64, [OutOfRange])
|
||||
from_numeral : Numeral -> Try(F64, [InvalidNumeral(Str)])
|
||||
|
||||
# Conversions to signed integers (all lossy - truncation + range check)
|
||||
to_i8_wrap : F64 -> I8
|
||||
to_i8_try : F64 -> Try(I8, [OutOfRange])
|
||||
to_i16_wrap : F64 -> I16
|
||||
to_i16_try : F64 -> Try(I16, [OutOfRange])
|
||||
to_i32_wrap : F64 -> I32
|
||||
to_i32_try : F64 -> Try(I32, [OutOfRange])
|
||||
to_i64_wrap : F64 -> I64
|
||||
to_i64_try : F64 -> Try(I64, [OutOfRange])
|
||||
to_i128_wrap : F64 -> I128
|
||||
to_i128_try : F64 -> Try(I128, [OutOfRange])
|
||||
|
||||
# Conversions to unsigned integers (all lossy - truncation + range check)
|
||||
to_u8_wrap : F64 -> U8
|
||||
to_u8_try : F64 -> Try(U8, [OutOfRange])
|
||||
to_u16_wrap : F64 -> U16
|
||||
to_u16_try : F64 -> Try(U16, [OutOfRange])
|
||||
to_u32_wrap : F64 -> U32
|
||||
to_u32_try : F64 -> Try(U32, [OutOfRange])
|
||||
to_u64_wrap : F64 -> U64
|
||||
to_u64_try : F64 -> Try(U64, [OutOfRange])
|
||||
to_u128_wrap : F64 -> U128
|
||||
to_u128_try : F64 -> Try(U128, [OutOfRange])
|
||||
|
||||
# Conversion to F32 (lossy narrowing)
|
||||
to_f32_wrap : F64 -> F32
|
||||
|
||||
to_f32_try : F64 -> Try(F32, [OutOfRange])
|
||||
to_f32_try = |num| {
|
||||
answer = f64_to_f32_try_unsafe(num)
|
||||
if answer.success != 0 { Ok(answer.val_or_memory_garbage) } else { Err(OutOfRange) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -523,3 +814,8 @@ Builtin :: [].{
|
|||
# Private top-level function for unsafe list access
|
||||
# This is a low-level operation that gets replaced by the compiler
|
||||
list_get_unsafe : List(item), U64 -> item
|
||||
|
||||
# Unsafe conversion functions - these return simple records instead of Try types
|
||||
# They are low-level operations that get replaced by the compiler
|
||||
# Note: success is U8 (0 = false, 1 = true) since Bool is not available at top level
|
||||
f64_to_f32_try_unsafe : F64 -> { success : U8, val_or_memory_garbage : F32 }
|
||||
|
|
|
|||
|
|
@ -1058,6 +1058,48 @@ pub fn toF64(arg: RocDec) callconv(.c) f64 {
|
|||
return @call(.always_inline, RocDec.toF64, .{arg});
|
||||
}
|
||||
|
||||
/// Convert Dec to F32 (lossy conversion)
|
||||
pub fn toF32(arg: RocDec) callconv(.c) f32 {
|
||||
return @floatCast(arg.toF64());
|
||||
}
|
||||
|
||||
/// Convert Dec to F32 with range check - returns null if out of range
|
||||
pub fn toF32Try(arg: RocDec) ?f32 {
|
||||
const f64_val = arg.toF64();
|
||||
// Check if the value is within F32 range
|
||||
if (f64_val > math.floatMax(f32) or f64_val < -math.floatMax(f32)) {
|
||||
return null;
|
||||
}
|
||||
// Also check for infinity (which would indicate overflow)
|
||||
const f32_val: f32 = @floatCast(f64_val);
|
||||
if (math.isInf(f32_val) and !math.isInf(f64_val)) {
|
||||
return null;
|
||||
}
|
||||
return f32_val;
|
||||
}
|
||||
|
||||
/// Convert Dec to integer by truncating the fractional part (wrapping on overflow)
|
||||
pub fn toIntWrap(comptime T: type, arg: RocDec) T {
|
||||
// Divide by one_point_zero_i128 to get the integer part
|
||||
const whole_part = @divTrunc(arg.num, RocDec.one_point_zero_i128);
|
||||
// Truncate to the target type (wrapping)
|
||||
// First cast the i128 to u128, then truncate to the target size, then cast back to T if needed
|
||||
const as_u128: u128 = @bitCast(whole_part);
|
||||
const truncated = @as(std.meta.Int(.unsigned, @bitSizeOf(T)), @truncate(as_u128));
|
||||
return @bitCast(truncated);
|
||||
}
|
||||
|
||||
/// Convert Dec to integer by truncating the fractional part (returns null if out of range)
|
||||
pub fn toIntTry(comptime T: type, arg: RocDec) ?T {
|
||||
// Divide by one_point_zero_i128 to get the integer part
|
||||
const whole_part = @divTrunc(arg.num, RocDec.one_point_zero_i128);
|
||||
// Check if it fits in the target type
|
||||
if (whole_part < math.minInt(T) or whole_part > math.maxInt(T)) {
|
||||
return null;
|
||||
}
|
||||
return @intCast(whole_part);
|
||||
}
|
||||
|
||||
/// TODO: Document exportFromInt.
|
||||
pub fn exportFromInt(comptime T: type, comptime name: []const u8) void {
|
||||
const f = struct {
|
||||
|
|
|
|||
|
|
@ -536,6 +536,244 @@ pub const Expr = union(enum) {
|
|||
i8_to_f32, // I8 -> F32 (safe)
|
||||
i8_to_f64, // I8 -> F64 (safe)
|
||||
i8_to_dec, // I8 -> Dec (safe)
|
||||
|
||||
// Numeric conversion operations (U16)
|
||||
u16_to_i8_wrap, // U16 -> I8 (wrapping)
|
||||
u16_to_i8_try, // U16 -> Try(I8, [OutOfRange])
|
||||
u16_to_i16_wrap, // U16 -> I16 (wrapping)
|
||||
u16_to_i16_try, // U16 -> Try(I16, [OutOfRange])
|
||||
u16_to_i32, // U16 -> I32 (safe)
|
||||
u16_to_i64, // U16 -> I64 (safe)
|
||||
u16_to_i128, // U16 -> I128 (safe)
|
||||
u16_to_u8_wrap, // U16 -> U8 (wrapping)
|
||||
u16_to_u8_try, // U16 -> Try(U8, [OutOfRange])
|
||||
u16_to_u32, // U16 -> U32 (safe)
|
||||
u16_to_u64, // U16 -> U64 (safe)
|
||||
u16_to_u128, // U16 -> U128 (safe)
|
||||
u16_to_f32, // U16 -> F32 (safe)
|
||||
u16_to_f64, // U16 -> F64 (safe)
|
||||
u16_to_dec, // U16 -> Dec (safe)
|
||||
|
||||
// Numeric conversion operations (I16)
|
||||
i16_to_i8_wrap, // I16 -> I8 (wrapping)
|
||||
i16_to_i8_try, // I16 -> Try(I8, [OutOfRange])
|
||||
i16_to_i32, // I16 -> I32 (safe)
|
||||
i16_to_i64, // I16 -> I64 (safe)
|
||||
i16_to_i128, // I16 -> I128 (safe)
|
||||
i16_to_u8_wrap, // I16 -> U8 (wrapping)
|
||||
i16_to_u8_try, // I16 -> Try(U8, [OutOfRange])
|
||||
i16_to_u16_wrap, // I16 -> U16 (wrapping)
|
||||
i16_to_u16_try, // I16 -> Try(U16, [OutOfRange])
|
||||
i16_to_u32_wrap, // I16 -> U32 (wrapping)
|
||||
i16_to_u32_try, // I16 -> Try(U32, [OutOfRange])
|
||||
i16_to_u64_wrap, // I16 -> U64 (wrapping)
|
||||
i16_to_u64_try, // I16 -> Try(U64, [OutOfRange])
|
||||
i16_to_u128_wrap, // I16 -> U128 (wrapping)
|
||||
i16_to_u128_try, // I16 -> Try(U128, [OutOfRange])
|
||||
i16_to_f32, // I16 -> F32 (safe)
|
||||
i16_to_f64, // I16 -> F64 (safe)
|
||||
i16_to_dec, // I16 -> Dec (safe)
|
||||
|
||||
// Numeric conversion operations (U32)
|
||||
u32_to_i8_wrap, // U32 -> I8 (wrapping)
|
||||
u32_to_i8_try, // U32 -> Try(I8, [OutOfRange])
|
||||
u32_to_i16_wrap, // U32 -> I16 (wrapping)
|
||||
u32_to_i16_try, // U32 -> Try(I16, [OutOfRange])
|
||||
u32_to_i32_wrap, // U32 -> I32 (wrapping)
|
||||
u32_to_i32_try, // U32 -> Try(I32, [OutOfRange])
|
||||
u32_to_i64, // U32 -> I64 (safe)
|
||||
u32_to_i128, // U32 -> I128 (safe)
|
||||
u32_to_u8_wrap, // U32 -> U8 (wrapping)
|
||||
u32_to_u8_try, // U32 -> Try(U8, [OutOfRange])
|
||||
u32_to_u16_wrap, // U32 -> U16 (wrapping)
|
||||
u32_to_u16_try, // U32 -> Try(U16, [OutOfRange])
|
||||
u32_to_u64, // U32 -> U64 (safe)
|
||||
u32_to_u128, // U32 -> U128 (safe)
|
||||
u32_to_f32, // U32 -> F32 (safe)
|
||||
u32_to_f64, // U32 -> F64 (safe)
|
||||
u32_to_dec, // U32 -> Dec (safe)
|
||||
|
||||
// Numeric conversion operations (I32)
|
||||
i32_to_i8_wrap, // I32 -> I8 (wrapping)
|
||||
i32_to_i8_try, // I32 -> Try(I8, [OutOfRange])
|
||||
i32_to_i16_wrap, // I32 -> I16 (wrapping)
|
||||
i32_to_i16_try, // I32 -> Try(I16, [OutOfRange])
|
||||
i32_to_i64, // I32 -> I64 (safe)
|
||||
i32_to_i128, // I32 -> I128 (safe)
|
||||
i32_to_u8_wrap, // I32 -> U8 (wrapping)
|
||||
i32_to_u8_try, // I32 -> Try(U8, [OutOfRange])
|
||||
i32_to_u16_wrap, // I32 -> U16 (wrapping)
|
||||
i32_to_u16_try, // I32 -> Try(U16, [OutOfRange])
|
||||
i32_to_u32_wrap, // I32 -> U32 (wrapping)
|
||||
i32_to_u32_try, // I32 -> Try(U32, [OutOfRange])
|
||||
i32_to_u64_wrap, // I32 -> U64 (wrapping)
|
||||
i32_to_u64_try, // I32 -> Try(U64, [OutOfRange])
|
||||
i32_to_u128_wrap, // I32 -> U128 (wrapping)
|
||||
i32_to_u128_try, // I32 -> Try(U128, [OutOfRange])
|
||||
i32_to_f32, // I32 -> F32 (safe)
|
||||
i32_to_f64, // I32 -> F64 (safe)
|
||||
i32_to_dec, // I32 -> Dec (safe)
|
||||
|
||||
// Numeric conversion operations (U64)
|
||||
u64_to_i8_wrap, // U64 -> I8 (wrapping)
|
||||
u64_to_i8_try, // U64 -> Try(I8, [OutOfRange])
|
||||
u64_to_i16_wrap, // U64 -> I16 (wrapping)
|
||||
u64_to_i16_try, // U64 -> Try(I16, [OutOfRange])
|
||||
u64_to_i32_wrap, // U64 -> I32 (wrapping)
|
||||
u64_to_i32_try, // U64 -> Try(I32, [OutOfRange])
|
||||
u64_to_i64_wrap, // U64 -> I64 (wrapping)
|
||||
u64_to_i64_try, // U64 -> Try(I64, [OutOfRange])
|
||||
u64_to_i128, // U64 -> I128 (safe)
|
||||
u64_to_u8_wrap, // U64 -> U8 (wrapping)
|
||||
u64_to_u8_try, // U64 -> Try(U8, [OutOfRange])
|
||||
u64_to_u16_wrap, // U64 -> U16 (wrapping)
|
||||
u64_to_u16_try, // U64 -> Try(U16, [OutOfRange])
|
||||
u64_to_u32_wrap, // U64 -> U32 (wrapping)
|
||||
u64_to_u32_try, // U64 -> Try(U32, [OutOfRange])
|
||||
u64_to_u128, // U64 -> U128 (safe)
|
||||
u64_to_f32, // U64 -> F32 (safe)
|
||||
u64_to_f64, // U64 -> F64 (safe)
|
||||
u64_to_dec, // U64 -> Dec (safe)
|
||||
|
||||
// Numeric conversion operations (I64)
|
||||
i64_to_i8_wrap, // I64 -> I8 (wrapping)
|
||||
i64_to_i8_try, // I64 -> Try(I8, [OutOfRange])
|
||||
i64_to_i16_wrap, // I64 -> I16 (wrapping)
|
||||
i64_to_i16_try, // I64 -> Try(I16, [OutOfRange])
|
||||
i64_to_i32_wrap, // I64 -> I32 (wrapping)
|
||||
i64_to_i32_try, // I64 -> Try(I32, [OutOfRange])
|
||||
i64_to_i128, // I64 -> I128 (safe)
|
||||
i64_to_u8_wrap, // I64 -> U8 (wrapping)
|
||||
i64_to_u8_try, // I64 -> Try(U8, [OutOfRange])
|
||||
i64_to_u16_wrap, // I64 -> U16 (wrapping)
|
||||
i64_to_u16_try, // I64 -> Try(U16, [OutOfRange])
|
||||
i64_to_u32_wrap, // I64 -> U32 (wrapping)
|
||||
i64_to_u32_try, // I64 -> Try(U32, [OutOfRange])
|
||||
i64_to_u64_wrap, // I64 -> U64 (wrapping)
|
||||
i64_to_u64_try, // I64 -> Try(U64, [OutOfRange])
|
||||
i64_to_u128_wrap, // I64 -> U128 (wrapping)
|
||||
i64_to_u128_try, // I64 -> Try(U128, [OutOfRange])
|
||||
i64_to_f32, // I64 -> F32 (safe)
|
||||
i64_to_f64, // I64 -> F64 (safe)
|
||||
i64_to_dec, // I64 -> Dec (safe)
|
||||
|
||||
// Numeric conversion operations (U128)
|
||||
u128_to_i8_wrap, // U128 -> I8 (wrapping)
|
||||
u128_to_i8_try, // U128 -> Try(I8, [OutOfRange])
|
||||
u128_to_i16_wrap, // U128 -> I16 (wrapping)
|
||||
u128_to_i16_try, // U128 -> Try(I16, [OutOfRange])
|
||||
u128_to_i32_wrap, // U128 -> I32 (wrapping)
|
||||
u128_to_i32_try, // U128 -> Try(I32, [OutOfRange])
|
||||
u128_to_i64_wrap, // U128 -> I64 (wrapping)
|
||||
u128_to_i64_try, // U128 -> Try(I64, [OutOfRange])
|
||||
u128_to_i128_wrap, // U128 -> I128 (wrapping)
|
||||
u128_to_i128_try, // U128 -> Try(I128, [OutOfRange])
|
||||
u128_to_u8_wrap, // U128 -> U8 (wrapping)
|
||||
u128_to_u8_try, // U128 -> Try(U8, [OutOfRange])
|
||||
u128_to_u16_wrap, // U128 -> U16 (wrapping)
|
||||
u128_to_u16_try, // U128 -> Try(U16, [OutOfRange])
|
||||
u128_to_u32_wrap, // U128 -> U32 (wrapping)
|
||||
u128_to_u32_try, // U128 -> Try(U32, [OutOfRange])
|
||||
u128_to_u64_wrap, // U128 -> U64 (wrapping)
|
||||
u128_to_u64_try, // U128 -> Try(U64, [OutOfRange])
|
||||
u128_to_f32, // U128 -> F32 (safe)
|
||||
u128_to_f64, // U128 -> F64 (safe)
|
||||
u128_to_dec_try_unsafe, // U128 -> { success: Bool, val: Dec }
|
||||
|
||||
// Numeric conversion operations (I128)
|
||||
i128_to_i8_wrap, // I128 -> I8 (wrapping)
|
||||
i128_to_i8_try, // I128 -> Try(I8, [OutOfRange])
|
||||
i128_to_i16_wrap, // I128 -> I16 (wrapping)
|
||||
i128_to_i16_try, // I128 -> Try(I16, [OutOfRange])
|
||||
i128_to_i32_wrap, // I128 -> I32 (wrapping)
|
||||
i128_to_i32_try, // I128 -> Try(I32, [OutOfRange])
|
||||
i128_to_i64_wrap, // I128 -> I64 (wrapping)
|
||||
i128_to_i64_try, // I128 -> Try(I64, [OutOfRange])
|
||||
i128_to_u8_wrap, // I128 -> U8 (wrapping)
|
||||
i128_to_u8_try, // I128 -> Try(U8, [OutOfRange])
|
||||
i128_to_u16_wrap, // I128 -> U16 (wrapping)
|
||||
i128_to_u16_try, // I128 -> Try(U16, [OutOfRange])
|
||||
i128_to_u32_wrap, // I128 -> U32 (wrapping)
|
||||
i128_to_u32_try, // I128 -> Try(U32, [OutOfRange])
|
||||
i128_to_u64_wrap, // I128 -> U64 (wrapping)
|
||||
i128_to_u64_try, // I128 -> Try(U64, [OutOfRange])
|
||||
i128_to_u128_wrap, // I128 -> U128 (wrapping)
|
||||
i128_to_u128_try, // I128 -> Try(U128, [OutOfRange])
|
||||
i128_to_f32, // I128 -> F32 (safe)
|
||||
i128_to_f64, // I128 -> F64 (safe)
|
||||
i128_to_dec_try_unsafe, // I128 -> { success: Bool, val: Dec }
|
||||
|
||||
// Numeric conversion operations (F32)
|
||||
f32_to_i8_trunc, // F32 -> I8 (truncating)
|
||||
f32_to_i8_try_unsafe, // F32 -> { is_int: Bool, in_range: Bool, val: I8 }
|
||||
f32_to_i16_trunc, // F32 -> I16 (truncating)
|
||||
f32_to_i16_try_unsafe, // F32 -> { is_int: Bool, in_range: Bool, val: I16 }
|
||||
f32_to_i32_trunc, // F32 -> I32 (truncating)
|
||||
f32_to_i32_try_unsafe, // F32 -> { is_int: Bool, in_range: Bool, val: I32 }
|
||||
f32_to_i64_trunc, // F32 -> I64 (truncating)
|
||||
f32_to_i64_try_unsafe, // F32 -> { is_int: Bool, in_range: Bool, val: I64 }
|
||||
f32_to_i128_trunc, // F32 -> I128 (truncating)
|
||||
f32_to_i128_try_unsafe, // F32 -> { is_int: Bool, in_range: Bool, val: I128 }
|
||||
f32_to_u8_trunc, // F32 -> U8 (truncating)
|
||||
f32_to_u8_try_unsafe, // F32 -> { is_int: Bool, in_range: Bool, val: U8 }
|
||||
f32_to_u16_trunc, // F32 -> U16 (truncating)
|
||||
f32_to_u16_try_unsafe, // F32 -> { is_int: Bool, in_range: Bool, val: U16 }
|
||||
f32_to_u32_trunc, // F32 -> U32 (truncating)
|
||||
f32_to_u32_try_unsafe, // F32 -> { is_int: Bool, in_range: Bool, val: U32 }
|
||||
f32_to_u64_trunc, // F32 -> U64 (truncating)
|
||||
f32_to_u64_try_unsafe, // F32 -> { is_int: Bool, in_range: Bool, val: U64 }
|
||||
f32_to_u128_trunc, // F32 -> U128 (truncating)
|
||||
f32_to_u128_try_unsafe, // F32 -> { is_int: Bool, in_range: Bool, val: U128 }
|
||||
f32_to_f64, // F32 -> F64 (safe widening)
|
||||
|
||||
// Numeric conversion operations (F64)
|
||||
f64_to_i8_trunc, // F64 -> I8 (truncating)
|
||||
f64_to_i8_try_unsafe, // F64 -> { is_int: Bool, in_range: Bool, val: I8 }
|
||||
f64_to_i16_trunc, // F64 -> I16 (truncating)
|
||||
f64_to_i16_try_unsafe, // F64 -> { is_int: Bool, in_range: Bool, val: I16 }
|
||||
f64_to_i32_trunc, // F64 -> I32 (truncating)
|
||||
f64_to_i32_try_unsafe, // F64 -> { is_int: Bool, in_range: Bool, val: I32 }
|
||||
f64_to_i64_trunc, // F64 -> I64 (truncating)
|
||||
f64_to_i64_try_unsafe, // F64 -> { is_int: Bool, in_range: Bool, val: I64 }
|
||||
f64_to_i128_trunc, // F64 -> I128 (truncating)
|
||||
f64_to_i128_try_unsafe, // F64 -> { is_int: Bool, in_range: Bool, val: I128 }
|
||||
f64_to_u8_trunc, // F64 -> U8 (truncating)
|
||||
f64_to_u8_try_unsafe, // F64 -> { is_int: Bool, in_range: Bool, val: U8 }
|
||||
f64_to_u16_trunc, // F64 -> U16 (truncating)
|
||||
f64_to_u16_try_unsafe, // F64 -> { is_int: Bool, in_range: Bool, val: U16 }
|
||||
f64_to_u32_trunc, // F64 -> U32 (truncating)
|
||||
f64_to_u32_try_unsafe, // F64 -> { is_int: Bool, in_range: Bool, val: U32 }
|
||||
f64_to_u64_trunc, // F64 -> U64 (truncating)
|
||||
f64_to_u64_try_unsafe, // F64 -> { is_int: Bool, in_range: Bool, val: U64 }
|
||||
f64_to_u128_trunc, // F64 -> U128 (truncating)
|
||||
f64_to_u128_try_unsafe, // F64 -> { is_int: Bool, in_range: Bool, val: U128 }
|
||||
f64_to_f32_wrap, // F64 -> F32 (lossy narrowing)
|
||||
f64_to_f32_try_unsafe, // F64 -> { success: Bool, val: F32 }
|
||||
|
||||
// Numeric conversion operations (Dec)
|
||||
dec_to_i8_trunc, // Dec -> I8 (truncating)
|
||||
dec_to_i8_try_unsafe, // Dec -> { is_int: Bool, in_range: Bool, val: I8 }
|
||||
dec_to_i16_trunc, // Dec -> I16 (truncating)
|
||||
dec_to_i16_try_unsafe, // Dec -> { is_int: Bool, in_range: Bool, val: I16 }
|
||||
dec_to_i32_trunc, // Dec -> I32 (truncating)
|
||||
dec_to_i32_try_unsafe, // Dec -> { is_int: Bool, in_range: Bool, val: I32 }
|
||||
dec_to_i64_trunc, // Dec -> I64 (truncating)
|
||||
dec_to_i64_try_unsafe, // Dec -> { is_int: Bool, in_range: Bool, val: I64 }
|
||||
dec_to_i128_trunc, // Dec -> I128 (truncating)
|
||||
dec_to_i128_try_unsafe, // Dec -> { is_int: Bool, val: I128 } - always in range
|
||||
dec_to_u8_trunc, // Dec -> U8 (truncating)
|
||||
dec_to_u8_try_unsafe, // Dec -> { is_int: Bool, in_range: Bool, val: U8 }
|
||||
dec_to_u16_trunc, // Dec -> U16 (truncating)
|
||||
dec_to_u16_try_unsafe, // Dec -> { is_int: Bool, in_range: Bool, val: U16 }
|
||||
dec_to_u32_trunc, // Dec -> U32 (truncating)
|
||||
dec_to_u32_try_unsafe, // Dec -> { is_int: Bool, in_range: Bool, val: U32 }
|
||||
dec_to_u64_trunc, // Dec -> U64 (truncating)
|
||||
dec_to_u64_try_unsafe, // Dec -> { is_int: Bool, in_range: Bool, val: U64 }
|
||||
dec_to_u128_trunc, // Dec -> U128 (truncating)
|
||||
dec_to_u128_try_unsafe, // Dec -> { is_int: Bool, in_range: Bool, val: U128 }
|
||||
dec_to_f32_wrap, // Dec -> F32 (lossy narrowing)
|
||||
dec_to_f32_try_unsafe, // Dec -> { success: Bool, val: F32 }
|
||||
dec_to_f64, // Dec -> F64 (lossy conversion)
|
||||
};
|
||||
|
||||
pub const Idx = enum(u32) { _ };
|
||||
|
|
|
|||
|
|
@ -570,6 +570,23 @@ pub const Interpreter = struct {
|
|||
return StackValue{ .layout = layout_val, .ptr = ptr, .is_initialized = true };
|
||||
}
|
||||
|
||||
/// Push raw bytes with a specific size and alignment (for building records/tuples)
|
||||
pub fn pushRawBytes(self: *Interpreter, size: usize, alignment: usize) !StackValue {
|
||||
if (size == 0) {
|
||||
return StackValue{ .layout = .{ .tag = .zst, .data = undefined }, .ptr = null, .is_initialized = true };
|
||||
}
|
||||
const align_enum: std.mem.Alignment = switch (alignment) {
|
||||
1 => .@"1",
|
||||
2 => .@"2",
|
||||
4 => .@"4",
|
||||
8 => .@"8",
|
||||
16 => .@"16",
|
||||
else => .@"1",
|
||||
};
|
||||
const ptr = try self.stack_memory.alloca(@intCast(size), align_enum);
|
||||
return StackValue{ .layout = .{ .tag = .zst, .data = undefined }, .ptr = ptr, .is_initialized = true };
|
||||
}
|
||||
|
||||
pub fn pushCopy(self: *Interpreter, src: StackValue, roc_ops: *RocOps) !StackValue {
|
||||
const size: u32 = if (src.layout.tag == .closure) src.getTotalSize(&self.runtime_layout_store) else self.runtime_layout_store.layoutSize(src.layout);
|
||||
const target_usize = self.runtime_layout_store.targetUsize();
|
||||
|
|
@ -2508,6 +2525,247 @@ pub const Interpreter = struct {
|
|||
.i8_to_f32 => return self.intToFloat(i8, f32, args),
|
||||
.i8_to_f64 => return self.intToFloat(i8, f64, args),
|
||||
.i8_to_dec => return self.intToDec(i8, args),
|
||||
|
||||
// U16 conversion operations
|
||||
.u16_to_i8_wrap => return self.intConvertWrap(u16, i8, args),
|
||||
.u16_to_i8_try => return self.intConvertTry(u16, i8, args, return_rt_var),
|
||||
.u16_to_i16_wrap => return self.intConvertWrap(u16, i16, args),
|
||||
.u16_to_i16_try => return self.intConvertTry(u16, i16, args, return_rt_var),
|
||||
.u16_to_i32 => return self.intConvert(u16, i32, args),
|
||||
.u16_to_i64 => return self.intConvert(u16, i64, args),
|
||||
.u16_to_i128 => return self.intConvert(u16, i128, args),
|
||||
.u16_to_u8_wrap => return self.intConvertWrap(u16, u8, args),
|
||||
.u16_to_u8_try => return self.intConvertTry(u16, u8, args, return_rt_var),
|
||||
.u16_to_u32 => return self.intConvert(u16, u32, args),
|
||||
.u16_to_u64 => return self.intConvert(u16, u64, args),
|
||||
.u16_to_u128 => return self.intConvert(u16, u128, args),
|
||||
.u16_to_f32 => return self.intToFloat(u16, f32, args),
|
||||
.u16_to_f64 => return self.intToFloat(u16, f64, args),
|
||||
.u16_to_dec => return self.intToDec(u16, args),
|
||||
|
||||
// I16 conversion operations
|
||||
.i16_to_i8_wrap => return self.intConvertWrap(i16, i8, args),
|
||||
.i16_to_i8_try => return self.intConvertTry(i16, i8, args, return_rt_var),
|
||||
.i16_to_i32 => return self.intConvert(i16, i32, args),
|
||||
.i16_to_i64 => return self.intConvert(i16, i64, args),
|
||||
.i16_to_i128 => return self.intConvert(i16, i128, args),
|
||||
.i16_to_u8_wrap => return self.intConvertWrap(i16, u8, args),
|
||||
.i16_to_u8_try => return self.intConvertTry(i16, u8, args, return_rt_var),
|
||||
.i16_to_u16_wrap => return self.intConvertWrap(i16, u16, args),
|
||||
.i16_to_u16_try => return self.intConvertTry(i16, u16, args, return_rt_var),
|
||||
.i16_to_u32_wrap => return self.intConvertWrap(i16, u32, args),
|
||||
.i16_to_u32_try => return self.intConvertTry(i16, u32, args, return_rt_var),
|
||||
.i16_to_u64_wrap => return self.intConvertWrap(i16, u64, args),
|
||||
.i16_to_u64_try => return self.intConvertTry(i16, u64, args, return_rt_var),
|
||||
.i16_to_u128_wrap => return self.intConvertWrap(i16, u128, args),
|
||||
.i16_to_u128_try => return self.intConvertTry(i16, u128, args, return_rt_var),
|
||||
.i16_to_f32 => return self.intToFloat(i16, f32, args),
|
||||
.i16_to_f64 => return self.intToFloat(i16, f64, args),
|
||||
.i16_to_dec => return self.intToDec(i16, args),
|
||||
|
||||
// U32 conversion operations
|
||||
.u32_to_i8_wrap => return self.intConvertWrap(u32, i8, args),
|
||||
.u32_to_i8_try => return self.intConvertTry(u32, i8, args, return_rt_var),
|
||||
.u32_to_i16_wrap => return self.intConvertWrap(u32, i16, args),
|
||||
.u32_to_i16_try => return self.intConvertTry(u32, i16, args, return_rt_var),
|
||||
.u32_to_i32_wrap => return self.intConvertWrap(u32, i32, args),
|
||||
.u32_to_i32_try => return self.intConvertTry(u32, i32, args, return_rt_var),
|
||||
.u32_to_i64 => return self.intConvert(u32, i64, args),
|
||||
.u32_to_i128 => return self.intConvert(u32, i128, args),
|
||||
.u32_to_u8_wrap => return self.intConvertWrap(u32, u8, args),
|
||||
.u32_to_u8_try => return self.intConvertTry(u32, u8, args, return_rt_var),
|
||||
.u32_to_u16_wrap => return self.intConvertWrap(u32, u16, args),
|
||||
.u32_to_u16_try => return self.intConvertTry(u32, u16, args, return_rt_var),
|
||||
.u32_to_u64 => return self.intConvert(u32, u64, args),
|
||||
.u32_to_u128 => return self.intConvert(u32, u128, args),
|
||||
.u32_to_f32 => return self.intToFloat(u32, f32, args),
|
||||
.u32_to_f64 => return self.intToFloat(u32, f64, args),
|
||||
.u32_to_dec => return self.intToDec(u32, args),
|
||||
|
||||
// I32 conversion operations
|
||||
.i32_to_i8_wrap => return self.intConvertWrap(i32, i8, args),
|
||||
.i32_to_i8_try => return self.intConvertTry(i32, i8, args, return_rt_var),
|
||||
.i32_to_i16_wrap => return self.intConvertWrap(i32, i16, args),
|
||||
.i32_to_i16_try => return self.intConvertTry(i32, i16, args, return_rt_var),
|
||||
.i32_to_i64 => return self.intConvert(i32, i64, args),
|
||||
.i32_to_i128 => return self.intConvert(i32, i128, args),
|
||||
.i32_to_u8_wrap => return self.intConvertWrap(i32, u8, args),
|
||||
.i32_to_u8_try => return self.intConvertTry(i32, u8, args, return_rt_var),
|
||||
.i32_to_u16_wrap => return self.intConvertWrap(i32, u16, args),
|
||||
.i32_to_u16_try => return self.intConvertTry(i32, u16, args, return_rt_var),
|
||||
.i32_to_u32_wrap => return self.intConvertWrap(i32, u32, args),
|
||||
.i32_to_u32_try => return self.intConvertTry(i32, u32, args, return_rt_var),
|
||||
.i32_to_u64_wrap => return self.intConvertWrap(i32, u64, args),
|
||||
.i32_to_u64_try => return self.intConvertTry(i32, u64, args, return_rt_var),
|
||||
.i32_to_u128_wrap => return self.intConvertWrap(i32, u128, args),
|
||||
.i32_to_u128_try => return self.intConvertTry(i32, u128, args, return_rt_var),
|
||||
.i32_to_f32 => return self.intToFloat(i32, f32, args),
|
||||
.i32_to_f64 => return self.intToFloat(i32, f64, args),
|
||||
.i32_to_dec => return self.intToDec(i32, args),
|
||||
|
||||
// U64 conversion operations
|
||||
.u64_to_i8_wrap => return self.intConvertWrap(u64, i8, args),
|
||||
.u64_to_i8_try => return self.intConvertTry(u64, i8, args, return_rt_var),
|
||||
.u64_to_i16_wrap => return self.intConvertWrap(u64, i16, args),
|
||||
.u64_to_i16_try => return self.intConvertTry(u64, i16, args, return_rt_var),
|
||||
.u64_to_i32_wrap => return self.intConvertWrap(u64, i32, args),
|
||||
.u64_to_i32_try => return self.intConvertTry(u64, i32, args, return_rt_var),
|
||||
.u64_to_i64_wrap => return self.intConvertWrap(u64, i64, args),
|
||||
.u64_to_i64_try => return self.intConvertTry(u64, i64, args, return_rt_var),
|
||||
.u64_to_i128 => return self.intConvert(u64, i128, args),
|
||||
.u64_to_u8_wrap => return self.intConvertWrap(u64, u8, args),
|
||||
.u64_to_u8_try => return self.intConvertTry(u64, u8, args, return_rt_var),
|
||||
.u64_to_u16_wrap => return self.intConvertWrap(u64, u16, args),
|
||||
.u64_to_u16_try => return self.intConvertTry(u64, u16, args, return_rt_var),
|
||||
.u64_to_u32_wrap => return self.intConvertWrap(u64, u32, args),
|
||||
.u64_to_u32_try => return self.intConvertTry(u64, u32, args, return_rt_var),
|
||||
.u64_to_u128 => return self.intConvert(u64, u128, args),
|
||||
.u64_to_f32 => return self.intToFloat(u64, f32, args),
|
||||
.u64_to_f64 => return self.intToFloat(u64, f64, args),
|
||||
.u64_to_dec => return self.intToDec(u64, args),
|
||||
|
||||
// I64 conversion operations
|
||||
.i64_to_i8_wrap => return self.intConvertWrap(i64, i8, args),
|
||||
.i64_to_i8_try => return self.intConvertTry(i64, i8, args, return_rt_var),
|
||||
.i64_to_i16_wrap => return self.intConvertWrap(i64, i16, args),
|
||||
.i64_to_i16_try => return self.intConvertTry(i64, i16, args, return_rt_var),
|
||||
.i64_to_i32_wrap => return self.intConvertWrap(i64, i32, args),
|
||||
.i64_to_i32_try => return self.intConvertTry(i64, i32, args, return_rt_var),
|
||||
.i64_to_i128 => return self.intConvert(i64, i128, args),
|
||||
.i64_to_u8_wrap => return self.intConvertWrap(i64, u8, args),
|
||||
.i64_to_u8_try => return self.intConvertTry(i64, u8, args, return_rt_var),
|
||||
.i64_to_u16_wrap => return self.intConvertWrap(i64, u16, args),
|
||||
.i64_to_u16_try => return self.intConvertTry(i64, u16, args, return_rt_var),
|
||||
.i64_to_u32_wrap => return self.intConvertWrap(i64, u32, args),
|
||||
.i64_to_u32_try => return self.intConvertTry(i64, u32, args, return_rt_var),
|
||||
.i64_to_u64_wrap => return self.intConvertWrap(i64, u64, args),
|
||||
.i64_to_u64_try => return self.intConvertTry(i64, u64, args, return_rt_var),
|
||||
.i64_to_u128_wrap => return self.intConvertWrap(i64, u128, args),
|
||||
.i64_to_u128_try => return self.intConvertTry(i64, u128, args, return_rt_var),
|
||||
.i64_to_f32 => return self.intToFloat(i64, f32, args),
|
||||
.i64_to_f64 => return self.intToFloat(i64, f64, args),
|
||||
.i64_to_dec => return self.intToDec(i64, args),
|
||||
|
||||
// U128 conversion operations
|
||||
.u128_to_i8_wrap => return self.intConvertWrap(u128, i8, args),
|
||||
.u128_to_i8_try => return self.intConvertTry(u128, i8, args, return_rt_var),
|
||||
.u128_to_i16_wrap => return self.intConvertWrap(u128, i16, args),
|
||||
.u128_to_i16_try => return self.intConvertTry(u128, i16, args, return_rt_var),
|
||||
.u128_to_i32_wrap => return self.intConvertWrap(u128, i32, args),
|
||||
.u128_to_i32_try => return self.intConvertTry(u128, i32, args, return_rt_var),
|
||||
.u128_to_i64_wrap => return self.intConvertWrap(u128, i64, args),
|
||||
.u128_to_i64_try => return self.intConvertTry(u128, i64, args, return_rt_var),
|
||||
.u128_to_i128_wrap => return self.intConvertWrap(u128, i128, args),
|
||||
.u128_to_i128_try => return self.intConvertTry(u128, i128, args, return_rt_var),
|
||||
.u128_to_u8_wrap => return self.intConvertWrap(u128, u8, args),
|
||||
.u128_to_u8_try => return self.intConvertTry(u128, u8, args, return_rt_var),
|
||||
.u128_to_u16_wrap => return self.intConvertWrap(u128, u16, args),
|
||||
.u128_to_u16_try => return self.intConvertTry(u128, u16, args, return_rt_var),
|
||||
.u128_to_u32_wrap => return self.intConvertWrap(u128, u32, args),
|
||||
.u128_to_u32_try => return self.intConvertTry(u128, u32, args, return_rt_var),
|
||||
.u128_to_u64_wrap => return self.intConvertWrap(u128, u64, args),
|
||||
.u128_to_u64_try => return self.intConvertTry(u128, u64, args, return_rt_var),
|
||||
.u128_to_f32 => return self.intToFloat(u128, f32, args),
|
||||
.u128_to_f64 => return self.intToFloat(u128, f64, args),
|
||||
|
||||
// I128 conversion operations
|
||||
.i128_to_i8_wrap => return self.intConvertWrap(i128, i8, args),
|
||||
.i128_to_i8_try => return self.intConvertTry(i128, i8, args, return_rt_var),
|
||||
.i128_to_i16_wrap => return self.intConvertWrap(i128, i16, args),
|
||||
.i128_to_i16_try => return self.intConvertTry(i128, i16, args, return_rt_var),
|
||||
.i128_to_i32_wrap => return self.intConvertWrap(i128, i32, args),
|
||||
.i128_to_i32_try => return self.intConvertTry(i128, i32, args, return_rt_var),
|
||||
.i128_to_i64_wrap => return self.intConvertWrap(i128, i64, args),
|
||||
.i128_to_i64_try => return self.intConvertTry(i128, i64, args, return_rt_var),
|
||||
.i128_to_u8_wrap => return self.intConvertWrap(i128, u8, args),
|
||||
.i128_to_u8_try => return self.intConvertTry(i128, u8, args, return_rt_var),
|
||||
.i128_to_u16_wrap => return self.intConvertWrap(i128, u16, args),
|
||||
.i128_to_u16_try => return self.intConvertTry(i128, u16, args, return_rt_var),
|
||||
.i128_to_u32_wrap => return self.intConvertWrap(i128, u32, args),
|
||||
.i128_to_u32_try => return self.intConvertTry(i128, u32, args, return_rt_var),
|
||||
.i128_to_u64_wrap => return self.intConvertWrap(i128, u64, args),
|
||||
.i128_to_u64_try => return self.intConvertTry(i128, u64, args, return_rt_var),
|
||||
.i128_to_u128_wrap => return self.intConvertWrap(i128, u128, args),
|
||||
.i128_to_u128_try => return self.intConvertTry(i128, u128, args, return_rt_var),
|
||||
.i128_to_f32 => return self.intToFloat(i128, f32, args),
|
||||
.i128_to_f64 => return self.intToFloat(i128, f64, args),
|
||||
|
||||
// U128 to Dec (try_unsafe - can overflow Dec's range)
|
||||
.u128_to_dec_try_unsafe => return self.intToDecTryUnsafe(u128, args),
|
||||
// I128 to Dec (try_unsafe - can overflow Dec's range)
|
||||
.i128_to_dec_try_unsafe => return self.intToDecTryUnsafe(i128, args),
|
||||
|
||||
// F32 conversion operations
|
||||
.f32_to_i8_trunc => return self.floatToIntTrunc(f32, i8, args),
|
||||
.f32_to_i8_try_unsafe => return self.floatToIntTryUnsafe(f32, i8, args),
|
||||
.f32_to_i16_trunc => return self.floatToIntTrunc(f32, i16, args),
|
||||
.f32_to_i16_try_unsafe => return self.floatToIntTryUnsafe(f32, i16, args),
|
||||
.f32_to_i32_trunc => return self.floatToIntTrunc(f32, i32, args),
|
||||
.f32_to_i32_try_unsafe => return self.floatToIntTryUnsafe(f32, i32, args),
|
||||
.f32_to_i64_trunc => return self.floatToIntTrunc(f32, i64, args),
|
||||
.f32_to_i64_try_unsafe => return self.floatToIntTryUnsafe(f32, i64, args),
|
||||
.f32_to_i128_trunc => return self.floatToIntTrunc(f32, i128, args),
|
||||
.f32_to_i128_try_unsafe => return self.floatToIntTryUnsafe(f32, i128, args),
|
||||
.f32_to_u8_trunc => return self.floatToIntTrunc(f32, u8, args),
|
||||
.f32_to_u8_try_unsafe => return self.floatToIntTryUnsafe(f32, u8, args),
|
||||
.f32_to_u16_trunc => return self.floatToIntTrunc(f32, u16, args),
|
||||
.f32_to_u16_try_unsafe => return self.floatToIntTryUnsafe(f32, u16, args),
|
||||
.f32_to_u32_trunc => return self.floatToIntTrunc(f32, u32, args),
|
||||
.f32_to_u32_try_unsafe => return self.floatToIntTryUnsafe(f32, u32, args),
|
||||
.f32_to_u64_trunc => return self.floatToIntTrunc(f32, u64, args),
|
||||
.f32_to_u64_try_unsafe => return self.floatToIntTryUnsafe(f32, u64, args),
|
||||
.f32_to_u128_trunc => return self.floatToIntTrunc(f32, u128, args),
|
||||
.f32_to_u128_try_unsafe => return self.floatToIntTryUnsafe(f32, u128, args),
|
||||
.f32_to_f64 => return self.floatWiden(f32, f64, args),
|
||||
|
||||
// F64 conversion operations
|
||||
.f64_to_i8_trunc => return self.floatToIntTrunc(f64, i8, args),
|
||||
.f64_to_i8_try_unsafe => return self.floatToIntTryUnsafe(f64, i8, args),
|
||||
.f64_to_i16_trunc => return self.floatToIntTrunc(f64, i16, args),
|
||||
.f64_to_i16_try_unsafe => return self.floatToIntTryUnsafe(f64, i16, args),
|
||||
.f64_to_i32_trunc => return self.floatToIntTrunc(f64, i32, args),
|
||||
.f64_to_i32_try_unsafe => return self.floatToIntTryUnsafe(f64, i32, args),
|
||||
.f64_to_i64_trunc => return self.floatToIntTrunc(f64, i64, args),
|
||||
.f64_to_i64_try_unsafe => return self.floatToIntTryUnsafe(f64, i64, args),
|
||||
.f64_to_i128_trunc => return self.floatToIntTrunc(f64, i128, args),
|
||||
.f64_to_i128_try_unsafe => return self.floatToIntTryUnsafe(f64, i128, args),
|
||||
.f64_to_u8_trunc => return self.floatToIntTrunc(f64, u8, args),
|
||||
.f64_to_u8_try_unsafe => return self.floatToIntTryUnsafe(f64, u8, args),
|
||||
.f64_to_u16_trunc => return self.floatToIntTrunc(f64, u16, args),
|
||||
.f64_to_u16_try_unsafe => return self.floatToIntTryUnsafe(f64, u16, args),
|
||||
.f64_to_u32_trunc => return self.floatToIntTrunc(f64, u32, args),
|
||||
.f64_to_u32_try_unsafe => return self.floatToIntTryUnsafe(f64, u32, args),
|
||||
.f64_to_u64_trunc => return self.floatToIntTrunc(f64, u64, args),
|
||||
.f64_to_u64_try_unsafe => return self.floatToIntTryUnsafe(f64, u64, args),
|
||||
.f64_to_u128_trunc => return self.floatToIntTrunc(f64, u128, args),
|
||||
.f64_to_u128_try_unsafe => return self.floatToIntTryUnsafe(f64, u128, args),
|
||||
.f64_to_f32_wrap => return self.floatNarrow(f64, f32, args),
|
||||
.f64_to_f32_try_unsafe => return self.floatNarrowTryUnsafe(f64, f32, args),
|
||||
|
||||
// Dec conversion operations
|
||||
.dec_to_i8_trunc => return self.decToIntTrunc(i8, args),
|
||||
.dec_to_i8_try_unsafe => return self.decToIntTryUnsafe(i8, args),
|
||||
.dec_to_i16_trunc => return self.decToIntTrunc(i16, args),
|
||||
.dec_to_i16_try_unsafe => return self.decToIntTryUnsafe(i16, args),
|
||||
.dec_to_i32_trunc => return self.decToIntTrunc(i32, args),
|
||||
.dec_to_i32_try_unsafe => return self.decToIntTryUnsafe(i32, args),
|
||||
.dec_to_i64_trunc => return self.decToIntTrunc(i64, args),
|
||||
.dec_to_i64_try_unsafe => return self.decToIntTryUnsafe(i64, args),
|
||||
.dec_to_i128_trunc => return self.decToIntTrunc(i128, args),
|
||||
.dec_to_i128_try_unsafe => return self.decToI128TryUnsafe(args),
|
||||
.dec_to_u8_trunc => return self.decToIntTrunc(u8, args),
|
||||
.dec_to_u8_try_unsafe => return self.decToIntTryUnsafe(u8, args),
|
||||
.dec_to_u16_trunc => return self.decToIntTrunc(u16, args),
|
||||
.dec_to_u16_try_unsafe => return self.decToIntTryUnsafe(u16, args),
|
||||
.dec_to_u32_trunc => return self.decToIntTrunc(u32, args),
|
||||
.dec_to_u32_try_unsafe => return self.decToIntTryUnsafe(u32, args),
|
||||
.dec_to_u64_trunc => return self.decToIntTrunc(u64, args),
|
||||
.dec_to_u64_try_unsafe => return self.decToIntTryUnsafe(u64, args),
|
||||
.dec_to_u128_trunc => return self.decToIntTrunc(u128, args),
|
||||
.dec_to_u128_try_unsafe => return self.decToIntTryUnsafe(u128, args),
|
||||
.dec_to_f32_wrap => return self.decToF32Wrap(args),
|
||||
.dec_to_f32_try_unsafe => return self.decToF32TryUnsafe(args),
|
||||
.dec_to_f64 => return self.decToF64(args),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2778,6 +3036,353 @@ pub const Interpreter = struct {
|
|||
return out;
|
||||
}
|
||||
|
||||
/// Helper for integer to Dec try_unsafe conversions (for u128/i128 which can overflow)
|
||||
/// Returns { success: Bool, val_or_memory_garbage: Dec }
|
||||
fn intToDecTryUnsafe(self: *Interpreter, comptime From: type, args: []const StackValue) !StackValue {
|
||||
std.debug.assert(args.len == 1);
|
||||
const int_arg = args[0];
|
||||
std.debug.assert(int_arg.ptr != null);
|
||||
|
||||
const from_value: From = @as(*const From, @ptrCast(@alignCast(int_arg.ptr.?))).*;
|
||||
|
||||
// Dec's max whole number is ~1.7×10^20, which is less than u128's max (~3.4×10^38)
|
||||
// Dec is stored as i128 * 10^18, so max safe value is i128.max / 10^18
|
||||
const dec_max_whole: i128 = @divFloor(std.math.maxInt(i128), RocDec.one_point_zero_i128);
|
||||
const dec_min_whole: i128 = @divFloor(std.math.minInt(i128), RocDec.one_point_zero_i128);
|
||||
|
||||
// Check if conversion is safe
|
||||
const success = if (From == u128)
|
||||
from_value <= @as(u128, @intCast(dec_max_whole))
|
||||
else if (From == i128)
|
||||
from_value >= dec_min_whole and from_value <= dec_max_whole
|
||||
else
|
||||
@compileError("intToDecTryUnsafe only supports u128 and i128");
|
||||
|
||||
// Build the result record: { success: Bool, val_or_memory_garbage: Dec }
|
||||
return try self.buildSuccessValRecord(success, if (success) RocDec{ .num = @as(i128, @intCast(from_value)) * RocDec.one_point_zero_i128 } else RocDec{ .num = 0 });
|
||||
}
|
||||
|
||||
/// Helper for float to int truncating conversions
|
||||
fn floatToIntTrunc(self: *Interpreter, comptime From: type, comptime To: type, args: []const StackValue) !StackValue {
|
||||
std.debug.assert(args.len == 1);
|
||||
const float_arg = args[0];
|
||||
std.debug.assert(float_arg.ptr != null);
|
||||
|
||||
const from_value: From = @as(*const From, @ptrCast(@alignCast(float_arg.ptr.?))).*;
|
||||
|
||||
// Truncate float to integer (clamping to range and truncating fractional part)
|
||||
const to_value: To = floatToIntSaturating(From, To, from_value);
|
||||
|
||||
const to_layout = Layout.int(comptime intTypeFromZigType(To));
|
||||
var out = try self.pushRaw(to_layout, 0);
|
||||
out.is_initialized = false;
|
||||
@as(*To, @ptrCast(@alignCast(out.ptr.?))).* = to_value;
|
||||
out.is_initialized = true;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Helper for float to int try_unsafe conversions
|
||||
/// Returns { is_int: Bool, in_range: Bool, val_or_memory_garbage: To }
|
||||
fn floatToIntTryUnsafe(self: *Interpreter, comptime From: type, comptime To: type, args: []const StackValue) !StackValue {
|
||||
std.debug.assert(args.len == 1);
|
||||
const float_arg = args[0];
|
||||
std.debug.assert(float_arg.ptr != null);
|
||||
|
||||
const from_value: From = @as(*const From, @ptrCast(@alignCast(float_arg.ptr.?))).*;
|
||||
|
||||
// Check if it's an integer (no fractional part) and not NaN/Inf
|
||||
const is_int = !std.math.isNan(from_value) and !std.math.isInf(from_value) and @trunc(from_value) == from_value;
|
||||
|
||||
// Check if in range for target type
|
||||
const min_val: From = @floatFromInt(std.math.minInt(To));
|
||||
const max_val: From = @floatFromInt(std.math.maxInt(To));
|
||||
const in_range = from_value >= min_val and from_value <= max_val;
|
||||
|
||||
const val: To = if (is_int and in_range) @intFromFloat(from_value) else 0;
|
||||
|
||||
// Build the result record: { is_int: Bool, in_range: Bool, val_or_memory_garbage: To }
|
||||
return try self.buildIsIntInRangeValRecord(is_int, in_range, To, val);
|
||||
}
|
||||
|
||||
/// Helper for float widening (F32 -> F64)
|
||||
fn floatWiden(self: *Interpreter, comptime From: type, comptime To: type, args: []const StackValue) !StackValue {
|
||||
std.debug.assert(args.len == 1);
|
||||
const float_arg = args[0];
|
||||
std.debug.assert(float_arg.ptr != null);
|
||||
|
||||
const from_value: From = @as(*const From, @ptrCast(@alignCast(float_arg.ptr.?))).*;
|
||||
const to_value: To = @floatCast(from_value);
|
||||
|
||||
const to_layout = Layout.frac(comptime fracTypeFromZigType(To));
|
||||
var out = try self.pushRaw(to_layout, 0);
|
||||
out.is_initialized = false;
|
||||
@as(*To, @ptrCast(@alignCast(out.ptr.?))).* = to_value;
|
||||
out.is_initialized = true;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Helper for float narrowing (F64 -> F32)
|
||||
fn floatNarrow(self: *Interpreter, comptime From: type, comptime To: type, args: []const StackValue) !StackValue {
|
||||
std.debug.assert(args.len == 1);
|
||||
const float_arg = args[0];
|
||||
std.debug.assert(float_arg.ptr != null);
|
||||
|
||||
const from_value: From = @as(*const From, @ptrCast(@alignCast(float_arg.ptr.?))).*;
|
||||
const to_value: To = @floatCast(from_value);
|
||||
|
||||
const to_layout = Layout.frac(comptime fracTypeFromZigType(To));
|
||||
var out = try self.pushRaw(to_layout, 0);
|
||||
out.is_initialized = false;
|
||||
@as(*To, @ptrCast(@alignCast(out.ptr.?))).* = to_value;
|
||||
out.is_initialized = true;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Helper for float narrowing try_unsafe (F64 -> F32)
|
||||
/// Returns { success: Bool, val_or_memory_garbage: F32 }
|
||||
fn floatNarrowTryUnsafe(self: *Interpreter, comptime From: type, comptime To: type, args: []const StackValue) !StackValue {
|
||||
std.debug.assert(args.len == 1);
|
||||
const float_arg = args[0];
|
||||
std.debug.assert(float_arg.ptr != null);
|
||||
|
||||
const from_value: From = @as(*const From, @ptrCast(@alignCast(float_arg.ptr.?))).*;
|
||||
const to_value: To = @floatCast(from_value);
|
||||
|
||||
// Check if the conversion is lossless (converting back gives the same value)
|
||||
// Also check for infinity which indicates overflow
|
||||
const success = !std.math.isInf(to_value) or std.math.isInf(from_value);
|
||||
const back: From = @floatCast(to_value);
|
||||
const lossless = from_value == back or (std.math.isNan(from_value) and std.math.isNan(back));
|
||||
|
||||
return try self.buildSuccessValRecordF32(success and lossless, to_value);
|
||||
}
|
||||
|
||||
/// Helper for Dec to int truncating conversions
|
||||
fn decToIntTrunc(self: *Interpreter, comptime To: type, args: []const StackValue) !StackValue {
|
||||
std.debug.assert(args.len == 1);
|
||||
const dec_arg = args[0];
|
||||
std.debug.assert(dec_arg.ptr != null);
|
||||
|
||||
const dec_value: RocDec = @as(*const RocDec, @ptrCast(@alignCast(dec_arg.ptr.?))).*;
|
||||
|
||||
// Get the whole number part by dividing by one_point_zero
|
||||
const whole_part = @divTrunc(dec_value.num, RocDec.one_point_zero_i128);
|
||||
|
||||
// Saturate to target range
|
||||
const to_value: To = std.math.cast(To, whole_part) orelse if (whole_part < 0) std.math.minInt(To) else std.math.maxInt(To);
|
||||
|
||||
const to_layout = Layout.int(comptime intTypeFromZigType(To));
|
||||
var out = try self.pushRaw(to_layout, 0);
|
||||
out.is_initialized = false;
|
||||
@as(*To, @ptrCast(@alignCast(out.ptr.?))).* = to_value;
|
||||
out.is_initialized = true;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Helper for Dec to int try_unsafe conversions
|
||||
/// Returns { is_int: Bool, in_range: Bool, val_or_memory_garbage: To }
|
||||
fn decToIntTryUnsafe(self: *Interpreter, comptime To: type, args: []const StackValue) !StackValue {
|
||||
std.debug.assert(args.len == 1);
|
||||
const dec_arg = args[0];
|
||||
std.debug.assert(dec_arg.ptr != null);
|
||||
|
||||
const dec_value: RocDec = @as(*const RocDec, @ptrCast(@alignCast(dec_arg.ptr.?))).*;
|
||||
|
||||
// Check if it's an integer (no fractional part)
|
||||
const remainder = @rem(dec_value.num, RocDec.one_point_zero_i128);
|
||||
const is_int = remainder == 0;
|
||||
|
||||
// Get the whole number part
|
||||
const whole_part = @divTrunc(dec_value.num, RocDec.one_point_zero_i128);
|
||||
|
||||
// Check if in range for target type
|
||||
const in_range = std.math.cast(To, whole_part) != null;
|
||||
|
||||
const val: To = if (is_int and in_range) @intCast(whole_part) else 0;
|
||||
|
||||
return try self.buildIsIntInRangeValRecord(is_int, in_range, To, val);
|
||||
}
|
||||
|
||||
/// Helper for Dec to i128 try_unsafe conversions (special case - always in range)
|
||||
/// Returns { is_int: Bool, val_or_memory_garbage: I128 }
|
||||
fn decToI128TryUnsafe(self: *Interpreter, args: []const StackValue) !StackValue {
|
||||
std.debug.assert(args.len == 1);
|
||||
const dec_arg = args[0];
|
||||
std.debug.assert(dec_arg.ptr != null);
|
||||
|
||||
const dec_value: RocDec = @as(*const RocDec, @ptrCast(@alignCast(dec_arg.ptr.?))).*;
|
||||
|
||||
// Check if it's an integer (no fractional part)
|
||||
const remainder = @rem(dec_value.num, RocDec.one_point_zero_i128);
|
||||
const is_int = remainder == 0;
|
||||
|
||||
// Get the whole number part - always fits in i128
|
||||
const whole_part = @divTrunc(dec_value.num, RocDec.one_point_zero_i128);
|
||||
|
||||
return try self.buildIsIntValRecord(is_int, whole_part);
|
||||
}
|
||||
|
||||
/// Helper for Dec to F32 wrapping conversion
|
||||
fn decToF32Wrap(self: *Interpreter, args: []const StackValue) !StackValue {
|
||||
std.debug.assert(args.len == 1);
|
||||
const dec_arg = args[0];
|
||||
std.debug.assert(dec_arg.ptr != null);
|
||||
|
||||
const dec_value: RocDec = @as(*const RocDec, @ptrCast(@alignCast(dec_arg.ptr.?))).*;
|
||||
const f64_value = dec_value.toF64();
|
||||
const f32_value: f32 = @floatCast(f64_value);
|
||||
|
||||
const to_layout = Layout.frac(.f32);
|
||||
var out = try self.pushRaw(to_layout, 0);
|
||||
out.is_initialized = false;
|
||||
@as(*f32, @ptrCast(@alignCast(out.ptr.?))).* = f32_value;
|
||||
out.is_initialized = true;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Helper for Dec to F32 try_unsafe conversion
|
||||
/// Returns { success: Bool, val_or_memory_garbage: F32 }
|
||||
fn decToF32TryUnsafe(self: *Interpreter, args: []const StackValue) !StackValue {
|
||||
std.debug.assert(args.len == 1);
|
||||
const dec_arg = args[0];
|
||||
std.debug.assert(dec_arg.ptr != null);
|
||||
|
||||
const dec_value: RocDec = @as(*const RocDec, @ptrCast(@alignCast(dec_arg.ptr.?))).*;
|
||||
const f64_value = dec_value.toF64();
|
||||
const f32_value: f32 = @floatCast(f64_value);
|
||||
|
||||
// Check if conversion is lossless by converting back
|
||||
const back_f64: f64 = @floatCast(f32_value);
|
||||
const back_dec = RocDec.fromF64(back_f64);
|
||||
const success = back_dec != null and back_dec.?.num == dec_value.num;
|
||||
|
||||
return try self.buildSuccessValRecordF32(success, f32_value);
|
||||
}
|
||||
|
||||
/// Helper for Dec to F64 conversion
|
||||
fn decToF64(self: *Interpreter, args: []const StackValue) !StackValue {
|
||||
std.debug.assert(args.len == 1);
|
||||
const dec_arg = args[0];
|
||||
std.debug.assert(dec_arg.ptr != null);
|
||||
|
||||
const dec_value: RocDec = @as(*const RocDec, @ptrCast(@alignCast(dec_arg.ptr.?))).*;
|
||||
const f64_value = dec_value.toF64();
|
||||
|
||||
const to_layout = Layout.frac(.f64);
|
||||
var out = try self.pushRaw(to_layout, 0);
|
||||
out.is_initialized = false;
|
||||
@as(*f64, @ptrCast(@alignCast(out.ptr.?))).* = f64_value;
|
||||
out.is_initialized = true;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Build a record { success: Bool, val_or_memory_garbage: Dec }
|
||||
fn buildSuccessValRecord(self: *Interpreter, success: bool, val: RocDec) !StackValue {
|
||||
// Layout: tuple (Dec, Bool) where element 0 is Dec (16 bytes) and element 1 is Bool (1 byte)
|
||||
// Total size with alignment: 24 bytes (16 for Dec + 8 for alignment of Bool field)
|
||||
const dec_layout = Layout.frac(.dec);
|
||||
const bool_layout = Layout.int(.u8);
|
||||
|
||||
// We need to create a tuple layout for the result
|
||||
// For now, allocate raw bytes and set them directly
|
||||
// The tuple is (val_or_memory_garbage: Dec, success: Bool)
|
||||
const tuple_size: usize = 24; // 16 bytes Dec + padding + 1 byte bool
|
||||
var out = try self.pushRawBytes(tuple_size, 16);
|
||||
out.is_initialized = false;
|
||||
|
||||
// Write Dec at offset 0
|
||||
@as(*RocDec, @ptrCast(@alignCast(out.ptr.?))).* = val;
|
||||
|
||||
// Write Bool at offset 16
|
||||
const bool_ptr: *u8 = @ptrFromInt(@intFromPtr(out.ptr.?) + 16);
|
||||
bool_ptr.* = @intFromBool(success);
|
||||
|
||||
out.is_initialized = true;
|
||||
// Layout is set by pushRawBytes as .zst since we're working with raw bytes
|
||||
_ = dec_layout;
|
||||
_ = bool_layout;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Build a record { success: Bool, val_or_memory_garbage: F32 }
|
||||
fn buildSuccessValRecordF32(self: *Interpreter, success: bool, val: f32) !StackValue {
|
||||
// Layout: tuple (F32, Bool) where element 0 is F32 (4 bytes) and element 1 is Bool (1 byte)
|
||||
const tuple_size: usize = 8; // 4 bytes F32 + padding + 1 byte bool
|
||||
var out = try self.pushRawBytes(tuple_size, 4);
|
||||
out.is_initialized = false;
|
||||
|
||||
// Write F32 at offset 0
|
||||
@as(*f32, @ptrCast(@alignCast(out.ptr.?))).* = val;
|
||||
|
||||
// Write Bool at offset 4
|
||||
const bool_ptr: *u8 = @ptrFromInt(@intFromPtr(out.ptr.?) + 4);
|
||||
bool_ptr.* = @intFromBool(success);
|
||||
|
||||
out.is_initialized = true;
|
||||
// Layout is set by pushRawBytes as .zst since we're working with raw bytes
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Build a record { is_int: Bool, in_range: Bool, val_or_memory_garbage: To }
|
||||
fn buildIsIntInRangeValRecord(self: *Interpreter, is_int: bool, in_range: bool, comptime To: type, val: To) !StackValue {
|
||||
// Layout depends on To's size
|
||||
const val_size = @sizeOf(To);
|
||||
const val_align = @alignOf(To);
|
||||
// Structure: (val, is_int, in_range) with proper alignment
|
||||
const tuple_size: usize = val_size + 2; // val + 2 bools
|
||||
const padded_size = (tuple_size + val_align - 1) / val_align * val_align;
|
||||
|
||||
var out = try self.pushRawBytes(padded_size, val_align);
|
||||
out.is_initialized = false;
|
||||
|
||||
// Write val at offset 0
|
||||
@as(*To, @ptrCast(@alignCast(out.ptr.?))).* = val;
|
||||
|
||||
// Write is_int at offset val_size
|
||||
const is_int_ptr: *u8 = @ptrFromInt(@intFromPtr(out.ptr.?) + val_size);
|
||||
is_int_ptr.* = @intFromBool(is_int);
|
||||
|
||||
// Write in_range at offset val_size + 1
|
||||
const in_range_ptr: *u8 = @ptrFromInt(@intFromPtr(out.ptr.?) + val_size + 1);
|
||||
in_range_ptr.* = @intFromBool(in_range);
|
||||
|
||||
out.is_initialized = true;
|
||||
// Layout is set by pushRawBytes as .zst since we're working with raw bytes
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Build a record { is_int: Bool, val_or_memory_garbage: I128 } (for dec_to_i128 which is always in range)
|
||||
fn buildIsIntValRecord(self: *Interpreter, is_int: bool, val: i128) !StackValue {
|
||||
// Layout: tuple (I128, Bool)
|
||||
const tuple_size: usize = 24; // 16 bytes I128 + padding + 1 byte bool
|
||||
var out = try self.pushRawBytes(tuple_size, 16);
|
||||
out.is_initialized = false;
|
||||
|
||||
// Write I128 at offset 0
|
||||
@as(*i128, @ptrCast(@alignCast(out.ptr.?))).* = val;
|
||||
|
||||
// Write Bool at offset 16
|
||||
const bool_ptr: *u8 = @ptrFromInt(@intFromPtr(out.ptr.?) + 16);
|
||||
bool_ptr.* = @intFromBool(is_int);
|
||||
|
||||
out.is_initialized = true;
|
||||
// Layout is set by pushRawBytes as .zst since we're working with raw bytes
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Helper to convert float to int with saturation (for trunc operations)
|
||||
fn floatToIntSaturating(comptime From: type, comptime To: type, value: From) To {
|
||||
if (std.math.isNan(value)) return 0;
|
||||
|
||||
const min_val: From = @floatFromInt(std.math.minInt(To));
|
||||
const max_val: From = @floatFromInt(std.math.maxInt(To));
|
||||
|
||||
if (value <= min_val) return std.math.minInt(To);
|
||||
if (value >= max_val) return std.math.maxInt(To);
|
||||
|
||||
return @intFromFloat(value);
|
||||
}
|
||||
|
||||
/// Convert Zig integer type to types.Int.Precision
|
||||
fn intTypeFromZigType(comptime T: type) types.Int.Precision {
|
||||
return switch (T) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue