From 59aa31cee5a795db8e5b11cc90e98eb8a8e7795b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kr=C3=BCger?= <45282134+UweKrueger@users.noreply.github.com> Date: Thu, 7 May 2020 04:34:18 +0200 Subject: [PATCH] cgen: string interpolation: optimize away some partial strings of 0 length --- vlib/v/gen/cgen.v | 25 ++++++++++++++++-------- vlib/v/gen/str.v | 3 +-- vlib/v/tests/string_interpolation_test.v | 12 +++++++----- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 61e2c7acf5..4eb2653ab0 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -2425,16 +2425,18 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { // Build the string with % mut fieldwidths := []int{} mut specs := []byte{} - mut num_fmts := 1 + mut end_string := false for i, val in node.vals { escaped_val := val.replace_each(['"', '\\"', '\r\n', '\\n', '\n', '\\n', '%', '%%']) - g.write(escaped_val) if i >= node.exprs.len { - fieldwidths << 0 - specs << `_` + if escaped_val.len > 0 { + end_string = true + g.write('\\000') + g.write(escaped_val) + } continue } - num_fmts++ + g.write(escaped_val) sym := g.table.get_type_symbol(node.expr_types[i]) sfmt := node.expr_fmts[i] mut fspec := `_` // placeholder @@ -2507,7 +2509,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { if fspec == `p` { g.write('${fmt}p') } else { - g.write('${fmt}l${fspec:c}') + g.write('${fmt}"PRI${fspec:c}PTR"') } } else if node.expr_types[i].is_int() { if fspec == `c` { @@ -2533,9 +2535,16 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { // TODO: better check this case g.write('${fmt}"PRId32"') } - g.write('\\000') + if i < node.exprs.len - 1 { + g.write('\\000') + } } - g.write('", $num_fmts, ') + num_string_parts := if end_string { + node.exprs.len+1 + } else { + node.exprs.len + } + g.write('", $num_string_parts, ') // Build args for i, expr in node.exprs { if node.expr_types[i] == table.string_type { diff --git a/vlib/v/gen/str.v b/vlib/v/gen/str.v index 4bf44d11df..5da8c560eb 100644 --- a/vlib/v/gen/str.v +++ b/vlib/v/gen/str.v @@ -70,8 +70,7 @@ string _STR(const char *fmt, int nfmts, ...) { //v_panic(tos3('Invaid format specifier')); } } else { - if (k) - _STR_PRINT_ARG(fmt, &buf, &nbytes, &memsize, k); + _STR_PRINT_ARG(fmt, &buf, &nbytes, &memsize, k); } fmt += k+1; } diff --git a/vlib/v/tests/string_interpolation_test.v b/vlib/v/tests/string_interpolation_test.v index bc076c2501..f5058e105b 100644 --- a/vlib/v/tests/string_interpolation_test.v +++ b/vlib/v/tests/string_interpolation_test.v @@ -98,8 +98,10 @@ fn test_inttypes_string_interpolation() { assert '${s:X}:${us:x}:${u16(uc):04x}' == 'A460:d431:00d9' assert '${i:x}:${ui:X}:${int(s):x}' == '9f430000:CBF6EFC7:ffffa460' assert '${l:x}:${ul:X}' == '9537727cad98876c:EF2B7D4001165BD2' - // TODO this does not work on Windows - // assert '${vp:p}:$bp' == '0xcbf6efc7:0x39e53208c' + // default pointer format is platform dependent, so try a few + assert '${vp:p}:$bp' == '0xcbf6efc7:0x39e53208c' || + '${vp:p}:$bp' == 'CBF6EFC7:39E53208C' || + '${vp:p}:$bp' == '00000000CBF6EFC7:000000039E53208C' } fn test_utf8_string_interpolation() { @@ -108,9 +110,9 @@ fn test_utf8_string_interpolation() { m := '10€' assert '$a $st $m' == 'à-côté Sträßle 10€' assert '>${a:10}< >${st:-8}< >${m:5}<-' == '> à-côté< >Sträßle < > 10€<-' - e := '\u20AC' // Eurosign - // TODO: this fails with MSVC and tcc - // assert '100.00 $e' == '100.00 €' + // e := '\u20AC' // Eurosign doesn' work with MSVC and tcc + e := '€' + assert '100.00 $e' == '100.00 €' m2 := 'Москва́' // cyrillic а́: combination of U+0430 and U+0301, UTF-8: d0 b0 cc 81 d := 'Antonín Dvořák' // latin á: U+00E1, UTF-8: c3 a1 assert ':${m2:7}:${d:-15}:' == ': Москва́:Antonín Dvořák :'