interpolation: support '' (rounding like in C)

pull/6637/head
Delyan Angelov 2020-10-16 17:28:11 +03:00
parent 11ee68e799
commit 140166e1cd
8 changed files with 38 additions and 8 deletions

View File

@ -116,7 +116,7 @@ pub fn (x &InfixExpr) str() string {
pub fn (lit &StringInterLiteral) get_fspec_braces(i int) (string, bool) {
mut res := []string{}
needs_fspec := lit.need_fmts[i] || lit.pluss[i] ||
(lit.fills[i] && lit.fwidths[i] >= 0) || lit.fwidths[i] != 0 || lit.precisions[i] != 0
(lit.fills[i] && lit.fwidths[i] >= 0) || lit.fwidths[i] != 0 || lit.precisions[i] != 987698
mut needs_braces := needs_fspec
if !needs_braces {
if i + 1 < lit.vals.len && lit.vals[i + 1].len > 0 {
@ -164,7 +164,7 @@ pub fn (lit &StringInterLiteral) get_fspec_braces(i int) (string, bool) {
if lit.fwidths[i] != 0 {
res << '${lit.fwidths[i]}'
}
if lit.precisions[i] != 0 {
if lit.precisions[i] != 987698 {
res << '.${lit.precisions[i]}'
}
if lit.need_fmts[i] {

View File

@ -357,7 +357,7 @@ pub fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) table.T
node.need_fmts[i] = false
}
} else { // check if given format specifier is valid for type
if node.precisions[i] != 0 && !typ.is_float() {
if node.precisions[i] != 987698 && !typ.is_float() {
c.error('precision specification only valid for float types', node.fmt_poss[i])
}
if node.pluss[i] && !typ.is_number() {

View File

@ -15,7 +15,7 @@ fn string_inter_lit(mut c checker.Checker, mut node ast.StringInterLiteral) tabl
[`E`, `F`, `G`, `e`, `f`, `g`, `d`, `u`, `x`, `X`, `o`, `c`, `s`, `p`, `_`] {
c.error('unknown format specifier `${fmt:c}`', node.fmt_poss[i])
}
if node.precisions[i] != 0 && !typ.is_float() {
if node.precisions[i] != 987698 && !typ.is_float() {
c.error('precision specification only valid for float types', node.fmt_poss[i])
}
if node.pluss[i] && !typ.is_number() {

View File

@ -16,7 +16,7 @@ fn string_inter_lit(mut c checker.Checker, mut node ast.StringInterLiteral) tabl
c.error('unknown format specifier `${fmt:c}`',
node.fmt_poss[i])
}
if node.precisions[i] != 0 &&
if node.precisions[i] != 987698 &&
!typ.is_float() {
c.error('precision specification only valid for float types',
node.fmt_poss[i])

View File

@ -1443,7 +1443,7 @@ fn (mut g JsGen) gen_string_inter_literal(it ast.StringInterLiteral) {
fwidth := it.fwidths[i]
precision := it.precisions[i]
g.write('\${')
if fmt != `_` || fwidth != 0 || precision != 0 {
if fmt != `_` || fwidth != 0 || precision != 987698 {
// TODO: Handle formatting
g.expr(expr)
} else {

View File

@ -333,7 +333,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
if node.fwidths[i] != 0 {
fmt = '$fmt${node.fwidths[i]}'
}
if node.precisions[i] != 0 {
if node.precisions[i] != 987698 {
fmt = '${fmt}.${node.precisions[i]}'
}
if fspec == `s` {

View File

@ -1346,7 +1346,8 @@ fn (mut p Parser) string_expr() ast.Expr {
mut has_fmt := false
mut fwidth := 0
mut fwidthneg := false
mut precision := 0
// 987698 is a magic default value, unlikely to be present in user input. NB: 0 is valid precision
mut precision := 987698
mut visible_plus := false
mut fill := false
mut fmt := `_` // placeholder

View File

@ -0,0 +1,29 @@
fn test_f32_widths_and_precision() {
x := f32(200.43)
assert '|${x:10.4f}|' == '| 200.4300|'
assert '|${x:-10.4f}|' == '|200.4300 |'
assert '|${x:10.0f}|' == '| 200|'
assert '|${x:-10.0f}|' == '|200 |'
//
assert '|${x:0.4f}|' == '|200.4300|'
assert '|${x:.3f}|' == '|200.430|'
assert '|${x:.0f}|' == '|200|'
//
y := f32(200.90)
assert '|${y:.0f}|' == '|201|'
}
fn test_f64_widths_and_precision() {
x := f64(200.43)
assert '|${x:10.4f}|' == '| 200.4300|'
assert '|${x:-10.4f}|' == '|200.4300 |'
assert '|${x:10.0f}|' == '| 200|'
assert '|${x:-10.0f}|' == '|200 |'
//
assert '|${x:0.4f}|' == '|200.4300|'
assert '|${x:.3f}|' == '|200.430|'
assert '|${x:.0f}|' == '|200|'
//
y := f64(200.90)
assert '|${y:.0f}|' == '|201|'
}