From bd10a63839322829336e521f4cc0fe52d4520186 Mon Sep 17 00:00:00 2001 From: penguindark <57967770+penguindark@users.noreply.github.com> Date: Mon, 6 Sep 2021 23:12:54 +0200 Subject: [PATCH] builtin: string interpolation: binary format support (#11421) --- vlib/builtin/string_int_test.v | 35 +++++++++++++++++++++++++++++ vlib/builtin/string_interpolation.v | 8 +++++++ vlib/v/checker/check_types.v | 10 ++++----- vlib/v/gen/c/str_intp.v | 4 ++++ 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/vlib/builtin/string_int_test.v b/vlib/builtin/string_int_test.v index a17563d2b7..3c055092c1 100644 --- a/vlib/builtin/string_int_test.v +++ b/vlib/builtin/string_int_test.v @@ -219,3 +219,38 @@ fn test_signed_cast() { assert '${u.f:G}' == '-INF' } } + +fn test_binary() { + i := i8(127) + u := u8(127) + assert '${i:08b}' == '01111111' + assert '${u:08b}' == '01111111' + assert '${i16(i):08b}' == '01111111' + assert '${u16(u):08b}' == '01111111' + assert '${int(i):08b}' == '01111111' + assert '${u32(u):08b}' == '01111111' + assert '${i64(i):08b}' == '01111111' + assert '${u64(u):08b}' == '01111111' + + n := i8(-1) + assert '${u8(-1):08b}' == '11111111' + assert '${u16(n):08b}' == '1111111111111111' + assert '${u32(n):08b}' == '11111111111111111111111111111111' + assert '${u64(n):08b}' == '1111111111111111111111111111111111111111111111111111111111111111' +} + +fn test_binary32() { + i := int(0x7fff_ffff) + u := u32(0x7fff_ffff) + assert '${i:032b}' == '01111111111111111111111111111111' + assert '${u:032b}' == '01111111111111111111111111111111' + assert '${i64(i):032b}' == '01111111111111111111111111111111' + assert '${u64(u):032b}' == '01111111111111111111111111111111' +} + +fn test_binary64() { + i := i64(0x7fff_ffff_ffff_ffff) + u := u64(0x7fff_ffff_ffff_ffff) + assert '${i:064b}' == '0111111111111111111111111111111111111111111111111111111111111111' + assert '${u:064b}' == '0111111111111111111111111111111111111111111111111111111111111111' +} diff --git a/vlib/builtin/string_interpolation.v b/vlib/builtin/string_interpolation.v index 10064ac6ea..8e6c23b8e8 100644 --- a/vlib/builtin/string_interpolation.v +++ b/vlib/builtin/string_interpolation.v @@ -252,6 +252,10 @@ fn (data StrIntpData) get_fmt_format(mut sb strings.Builder) { } strconv.format_dec_sb(abs64(d), bf, mut sb) } else { + // binary, we use 3 for binary + if base == 3 { + base = 2 + } mut hx := strconv.format_int(d, base) if upper_case { tmp := hx @@ -287,6 +291,10 @@ fn (data StrIntpData) get_fmt_format(mut sb strings.Builder) { } strconv.format_dec_sb(d, bf, mut sb) } else { + // binary, we use 3 for binary + if base == 3 { + base = 2 + } mut hx := strconv.format_uint(d, base) if upper_case { tmp := hx diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index a292508a7b..8bc96c3d28 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -451,8 +451,7 @@ pub fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) ast.Typ mut fmt := node.fmts[i] // analyze and validate format specifier if fmt !in [`E`, `F`, `G`, `e`, `f`, `g`, `d`, `u`, `x`, `X`, `o`, `c`, `s`, `S`, `p`, - `_`, - ] { + `b`, `_`] { c.error('unknown format specifier `${fmt:c}`', node.fmt_poss[i]) } if fmt == `_` { // set default representation for type if none has been given @@ -473,9 +472,10 @@ pub fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) ast.Typ if node.pluss[i] && !typ.is_number() { c.error('plus prefix only allowed for numbers', node.fmt_poss[i]) } - if (typ.is_unsigned() && fmt !in [`u`, `x`, `X`, `o`, `c`]) - || (typ.is_signed() && fmt !in [`d`, `x`, `X`, `o`, `c`]) - || (typ.is_int_literal() && fmt !in [`d`, `c`, `x`, `X`, `o`, `u`, `x`, `X`, `o`]) + if (typ.is_unsigned() && fmt !in [`u`, `x`, `X`, `o`, `c`, `b`]) + || (typ.is_signed() && fmt !in [`d`, `x`, `X`, `o`, `c`, `b`]) + || (typ.is_int_literal() + && fmt !in [`d`, `c`, `x`, `X`, `o`, `u`, `x`, `X`, `o`, `b`]) || (typ.is_float() && fmt !in [`E`, `F`, `G`, `e`, `f`, `g`]) || (typ.is_pointer() && fmt !in [`p`, `x`, `X`]) || (typ.is_string() && fmt !in [`s`, `S`]) diff --git a/vlib/v/gen/c/str_intp.v b/vlib/v/gen/c/str_intp.v index 7ace443a12..a3daef03bb 100644 --- a/vlib/v/gen/c/str_intp.v +++ b/vlib/v/gen/c/str_intp.v @@ -76,6 +76,10 @@ fn (mut g Gen) str_format(node ast.StringInterLiteral, i int) (u64, string) { if fspec == `o` { base = 8 - 2 // our base start from 2 } + // binary format + if fspec == `b` { + base = 1 // our base start from 2 we use 1 for binary + } if fspec == `c` { fmt_type = .si_c } else {