1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

all: rollback to old interpolation (step 1) (#16370)

This commit is contained in:
shove 2022-11-09 16:57:54 +08:00 committed by GitHub
parent 7830597b66
commit dd5f6186a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 32 additions and 131 deletions

View File

@ -216,7 +216,6 @@ pub:
fills []bool
fmt_poss []token.Pos
pos token.Pos
has_dollar []bool // two interpolation ways are temporarily supported
pub mut:
exprs []Expr
expr_types []Type

View File

@ -230,7 +230,7 @@ pub fn (lit &StringInterLiteral) get_fspec_braces(i int) (string, bool) {
needs_fspec := lit.need_fmts[i] || lit.pluss[i]
|| (lit.fills[i] && lit.fwidths[i] >= 0) || lit.fwidths[i] != 0
|| lit.precisions[i] != 987698
mut needs_braces := !lit.has_dollar[i] || needs_fspec
mut needs_braces := needs_fspec
sx := lit.exprs[i].str()
if sx.contains(r'"') || sx.contains(r"'") {
needs_braces = true
@ -480,9 +480,7 @@ pub fn (x Expr) str() string {
if i >= x.exprs.len {
break
}
if x.has_dollar[i] {
res.write_string('$')
}
res.write_string('$')
fspec_str, needs_braces := x.get_fspec_braces(i)
if needs_braces {
res.write_string('{')

View File

@ -1,5 +1,5 @@
vlib/v/checker/tests/str_interpol_invalid_err.vv:8:13: error: illegal format specifier `x` for type `[]int`
6 |
6 |
7 | fn main() {
8 | _ = '${[1]:x}'
| ^
@ -25,30 +25,23 @@ vlib/v/checker/tests/str_interpol_invalid_err.vv:11:13: error: illegal format sp
11 | _ = '${[1]:f}'
| ^
12 | _ := '${none:F}'
13 | _ = '${{"a": "b"}:x}'
13 | // _ = '${{"a": "b"}:x}'
vlib/v/checker/tests/str_interpol_invalid_err.vv:12:15: error: illegal format specifier `F` for type `none`
10 | _ = '${Foo{}:x}'
11 | _ = '${[1]:f}'
12 | _ := '${none:F}'
| ^
13 | _ = '${{"a": "b"}:x}'
13 | // _ = '${{"a": "b"}:x}'
14 | _ = '${Alias(Foo{}):x}'
vlib/v/checker/tests/str_interpol_invalid_err.vv:13:20: error: illegal format specifier `x` for type `map[string]string`
11 | _ = '${[1]:f}'
12 | _ := '${none:F}'
13 | _ = '${{"a": "b"}:x}'
| ^
14 | _ = '${Alias(Foo{}):x}'
15 | _ = '${SumType(int(5)):o}'
vlib/v/checker/tests/str_interpol_invalid_err.vv:14:22: error: illegal format specifier `x` for type `Alias`
12 | _ := '${none:F}'
13 | _ = '${{"a": "b"}:x}'
13 | // _ = '${{"a": "b"}:x}'
14 | _ = '${Alias(Foo{}):x}'
| ^
15 | _ = '${SumType(int(5)):o}'
16 | }
vlib/v/checker/tests/str_interpol_invalid_err.vv:15:25: error: illegal format specifier `o` for type `SumType`
13 | _ = '${{"a": "b"}:x}'
13 | // _ = '${{"a": "b"}:x}'
14 | _ = '${Alias(Foo{}):x}'
15 | _ = '${SumType(int(5)):o}'
| ^

View File

@ -10,7 +10,7 @@ fn main() {
_ = '${Foo{}:x}'
_ = '${[1]:f}'
_ := '${none:F}'
_ = '${{"a": "b"}:x}'
// _ = '${{"a": "b"}:x}'
_ = '${Alias(Foo{}):x}'
_ = '${SumType(int(5)):o}'
}

View File

@ -2706,9 +2706,7 @@ pub fn (mut f Fmt) string_inter_literal(node ast.StringInterLiteral) {
if i >= node.exprs.len {
break
}
if node.has_dollar[i] {
f.write('$')
}
f.write('$')
fspec_str, needs_braces := node.get_fspec_braces(i)
if needs_braces {
f.write('{')

View File

@ -3056,7 +3056,7 @@ fn (mut p Parser) string_expr() ast.Expr {
val := p.tok.lit
mut pos := p.tok.pos()
pos.last_line = pos.line_nr + val.count('\n')
if p.peek_tok.kind != .str_dollar && p.peek_tok.kind != .str_lcbr {
if p.peek_tok.kind != .str_dollar {
p.next()
p.filter_string_vet_errors(pos)
node = ast.StringLiteral{
@ -3076,16 +3076,14 @@ fn (mut p Parser) string_expr() ast.Expr {
mut fills := []bool{}
mut fmts := []u8{}
mut fposs := []token.Pos{}
mut has_dollar := []bool{}
// Handle $ interpolation
p.inside_str_interp = true
for p.tok.kind == .string {
vals << p.tok.lit
p.next()
if p.tok.kind != .str_dollar && p.tok.kind != .str_lcbr {
if p.tok.kind != .str_dollar {
break
}
has_dollar_ := p.tok.kind == .str_dollar
p.next()
exprs << p.expr(0)
mut has_fmt := false
@ -3138,7 +3136,6 @@ fn (mut p Parser) string_expr() ast.Expr {
fmts << fmt
fills << fill
fposs << p.prev_tok.pos()
has_dollar << has_dollar_
}
pos = pos.extend(p.prev_tok.pos())
p.filter_string_vet_errors(pos)
@ -3153,7 +3150,6 @@ fn (mut p Parser) string_expr() ast.Expr {
fmts: fmts
fmt_poss: fposs
pos: pos
has_dollar: has_dollar
}
// need_fmts: prelimery - until checker finds out if really needed
p.inside_str_interp = false

View File

@ -37,7 +37,6 @@ pub mut:
is_inter_start bool // for hacky string interpolation TODO simplify
is_inter_end bool
is_enclosed_inter bool
is_inside_interpolation bool // avoid nesting interpolation
line_comment string
last_lt int = -1 // position of latest <
is_started bool
@ -109,7 +108,7 @@ pub enum CommentsMode {
// new scanner from file.
pub fn new_scanner_file(file_path string, comments_mode CommentsMode, pref &pref.Preferences) !&Scanner {
if !os.is_file(file_path) {
return error('{file_path} is not a .v file')
return error('$file_path is not a .v file')
}
raw_text := util.read_file(file_path) or { return err }
mut s := &Scanner{
@ -287,7 +286,7 @@ fn (mut s Scanner) ident_bin_number() string {
s.error('number part of this binary is not provided')
} else if has_wrong_digit {
s.pos = first_wrong_digit_pos // adjust error position
s.error('this binary number has unsuitable digit `{first_wrong_digit.str()}`')
s.error('this binary number has unsuitable digit `$first_wrong_digit.str()`')
}
number := s.num_lit(start_pos, s.pos)
s.pos--
@ -331,7 +330,7 @@ fn (mut s Scanner) ident_hex_number() string {
s.error('number part of this hexadecimal is not provided')
} else if has_wrong_digit {
s.pos = first_wrong_digit_pos // adjust error position
s.error('this hexadecimal number has unsuitable digit `{first_wrong_digit.str()}`')
s.error('this hexadecimal number has unsuitable digit `$first_wrong_digit.str()`')
}
number := s.num_lit(start_pos, s.pos)
s.pos--
@ -371,7 +370,7 @@ fn (mut s Scanner) ident_oct_number() string {
s.error('number part of this octal is not provided')
} else if has_wrong_digit {
s.pos = first_wrong_digit_pos // adjust error position
s.error('this octal number has unsuitable digit `{first_wrong_digit.str()}`')
s.error('this octal number has unsuitable digit `$first_wrong_digit.str()`')
}
number := s.num_lit(start_pos, s.pos)
s.pos--
@ -447,7 +446,7 @@ fn (mut s Scanner) ident_dec_number() string {
symbol_length++
}
float_symbol := s.text[s.pos - 2 - symbol_length..s.pos - 1]
s.warn('float literals should have a digit after the decimal point, e.g. `{float_symbol}.0`')
s.warn('float literals should have a digit after the decimal point, e.g. `${float_symbol}.0`')
}
}
}
@ -481,7 +480,7 @@ fn (mut s Scanner) ident_dec_number() string {
// error check: wrong digit
s.pos = first_wrong_digit_pos // adjust error position
if !s.pref.translated {
s.error('this number has unsuitable digit `{first_wrong_digit.str()}`')
s.error('this number has unsuitable digit `$first_wrong_digit.str()`')
}
} else if s.text[s.pos - 1] in [`e`, `E`] {
// error check: 5e
@ -544,7 +543,7 @@ fn (mut s Scanner) end_of_file() token.Token {
if s.eofs > 50 {
s.line_nr--
panic(
'the end of file `{s.file_path}` has been reached 50 times already, the v parser is probably stuck.\n' +
'the end of file `$s.file_path` has been reached 50 times already, the v parser is probably stuck.\n' +
'This should not happen. Please report the bug here, and include the last 2-3 lines of your source code:\n' +
'https://github.com/vlang/v/issues/new?labels=Bug&template=bug_report.md')
}
@ -567,7 +566,7 @@ fn (mut s Scanner) scan_all_tokens_in_buffer() {
s.tidx = 0
$if debugscanner ? {
for t in s.all_tokens {
eprintln('> tidx:{t.tidx:-5} | kind: {t.kind:-10} | lit: {t.lit}')
eprintln('> tidx:${t.tidx:-5} | kind: ${t.kind:-10} | lit: $t.lit')
}
}
}
@ -678,14 +677,13 @@ fn (mut s Scanner) text_scan() token.Token {
s.is_inter_end = true
s.is_inter_start = false
s.is_inside_string = false
s.is_inside_interpolation = false
}
}
// end of `$expr`
// allow `'$a.b'` and `'$a.c()'`
if s.is_inter_start && next_char == `\\`
&& s.look_ahead(2) !in [`x`, `n`, `r`, `\\`, `t`, `e`, `"`, `'`] {
s.warn('unknown escape sequence \\{s.look_ahead(2)}')
s.warn('unknown escape sequence \\${s.look_ahead(2)}')
}
if s.is_inter_start && next_char == `(` {
if s.look_ahead(2) != `)` {
@ -694,7 +692,6 @@ fn (mut s Scanner) text_scan() token.Token {
} else if s.is_inter_start && next_char != `.` {
s.is_inter_end = true
s.is_inter_start = false
s.is_inside_interpolation = false
}
return s.new_token(.name, name, name.len)
} else if c.is_digit() || (c == `.` && nextc.is_digit()) {
@ -723,7 +720,6 @@ fn (mut s Scanner) text_scan() token.Token {
s.is_inter_start = false
if next_char == s.quote {
s.is_inside_string = false
s.is_inside_interpolation = false
}
return s.new_token(.rpar, '', 1)
}
@ -810,12 +806,10 @@ fn (mut s Scanner) text_scan() token.Token {
prev_char := s.text[s.pos - 1]
next_char := s.text[s.pos + 1]
// Handle new `hello {name}` string interpolation
if !s.is_inside_interpolation && !next_char.is_space() && next_char != `}`
&& prev_char != `$` {
s.is_inside_interpolation = true
return s.new_token(.str_lcbr, '', 1)
if !next_char.is_space() && next_char != `}` && prev_char != `$` {
return s.new_token(.str_dollar, '', 1)
}
if s.is_inside_interpolation && prev_char == `$` {
if prev_char == `$` {
// Skip { in `${` in strings
continue
} else {
@ -826,7 +820,6 @@ fn (mut s Scanner) text_scan() token.Token {
}
`$` {
if s.is_inside_string {
s.is_inside_interpolation = true
return s.new_token(.str_dollar, '', 1)
} else {
return s.new_token(.dollar, '', 1)
@ -844,11 +837,9 @@ fn (mut s Scanner) text_scan() token.Token {
if s.text[s.pos] == s.quote {
s.is_inside_string = false
s.is_enclosed_inter = false
s.is_inside_interpolation = false
return s.new_token(.string, '', 1)
}
s.is_enclosed_inter = false
s.is_inside_interpolation = false
ident_string := s.ident_string()
return s.new_token(.string, ident_string, ident_string.len + 2) // + two quotes
} else {
@ -901,7 +892,7 @@ fn (mut s Scanner) text_scan() token.Token {
mut at_error_msg := '@ must be used before keywords or compile time variables (e.g. `@type string` or `@FN`)'
// If name is all uppercase, the user is probably looking for a compile time variable ("at-token")
if name.is_upper() {
at_error_msg += '\nAvailable compile time variables:\n{token.valid_at_tokens}'
at_error_msg += '\nAvailable compile time variables:\n$token.valid_at_tokens'
}
s.error(at_error_msg)
}
@ -1125,7 +1116,7 @@ fn (mut s Scanner) invalid_character() {
len := utf8_char_len(s.text[s.pos])
end := mathutil.min(s.pos + len, s.text.len)
c := s.text[s.pos..end]
s.error('invalid character `{c}`')
s.error('invalid character `$c`')
}
fn (s &Scanner) current_column() int {
@ -1228,7 +1219,6 @@ fn (mut s Scanner) ident_string() string {
&& s.count_symbol_before(s.pos - 2, scanner.backslash) % 2 == 0 {
s.is_inside_string = true
s.is_enclosed_inter = true
s.is_inside_interpolation = true
// so that s.pos points to $ at the next step
s.pos -= 2
break
@ -1238,7 +1228,6 @@ fn (mut s Scanner) ident_string() string {
&& s.count_symbol_before(s.pos - 2, scanner.backslash) % 2 == 0 {
s.is_inside_string = true
s.is_inter_start = true
s.is_inside_interpolation = true
s.pos -= 2
break
}
@ -1410,7 +1399,7 @@ fn (mut s Scanner) decode_u_escape_single(str string, idx int) (int, string) {
escaped_code_point := strconv.parse_uint(str[idx + 2..end_idx], 16, 32) or { 0 }
// Check if Escaped Code Point is invalid or not
if rune(escaped_code_point).length_in_bytes() == -1 {
s.error('invalid unicode point `{str}`')
s.error('invalid unicode point `$str`')
}
return end_idx, utf32_to_str(u32(escaped_code_point))
@ -1531,15 +1520,15 @@ fn (mut s Scanner) ident_char() string {
u := c.runes()
if u.len != 1 {
if escaped_hex || escaped_unicode {
s.error('invalid character literal `{orig}` => `{c}` ({u}) (escape sequence did not refer to a singular rune)')
s.error('invalid character literal `$orig` => `$c` ($u) (escape sequence did not refer to a singular rune)')
} else if u.len == 0 {
s.add_error_detail_with_pos('use quotes for strings, backticks for characters',
lspos)
s.error('invalid empty character literal `{orig}`')
s.error('invalid empty character literal `$orig`')
} else {
s.add_error_detail_with_pos('use quotes for strings, backticks for characters',
lspos)
s.error('invalid character literal `{orig}` => `{c}` ({u}) (more than one character)')
s.error('invalid character literal `$orig` => `$c` ($u) (more than one character)')
}
}
}
@ -1713,6 +1702,6 @@ fn (mut s Scanner) vet_error(msg string, fix vet.FixKind) {
fn (mut s Scanner) trace(fbase string, message string) {
if s.file_base == fbase {
println('> s.trace | {fbase:-10s} | {message}')
println('> s.trace | ${fbase:-10s} | $message')
}
}

View File

@ -1,2 +0,0 @@
Foo = def
Foo = def

View File

@ -1,9 +0,0 @@
enum Foo {
abc
def
}
fn main() {
println('Foo = {Foo.def}')
println('Foo = {unsafe { Foo(1) }}')
}

View File

@ -1,57 +0,0 @@
fn test_string_new_interpolation() {
a, b, c, d := 1, 2, 3, 4
println('{a}{b}{c}{d}')
assert '{a}{b}{c}{d}' == '1234'
println('{a} {b} {c} {d}')
assert '{a} {b} {c} {d}' == '1 2 3 4'
println('{a}{{b}}')
assert '{a}{{b}}' == '1{2}'
println('{a}\{{b}}')
assert '{a}\{{b}}' == '1{2}'
println('{a}{{{{{b}}}}}')
assert '{a}{{{{{b}}}}}' == '1{{{{2}}}}'
s := 'hello'
println('{s == 'hello'}')
assert '{s == 'hello'}' == 'true'
println('{s != 'hello'}')
assert '{s != 'hello'}' == 'false'
n := 22
println('{n >= 10}')
assert '{n >= 10}' == 'true'
println('{n <= 10}')
assert '{n <= 10}' == 'false'
println('{n:10}')
assert '{n:10}' == ' 22'
f := 2.234
println('{f:05.2f}')
assert '{f:05.2f}' == '02.23'
println('{@FILE}')
assert '{@FILE}'.contains('string_new_interpolation_test.v')
ret := foo()
println(ret)
assert ret == r'[]T{aaa, bbb, ccc}'
}
fn foo() string {
match true {
true {
fields := ['aaa', 'bbb', 'ccc']
return '[]T{{fields.join(', ')}}'
}
else {
fields := ['aaa', 'bbb', 'ccc']
return 'const ({fields.join(' ')})'
}
}
}

View File

@ -46,8 +46,7 @@ pub enum Kind {
hash // #
dollar // $
at // @
str_dollar // ${} or $, old interpolation
str_lcbr // {interpolation
str_dollar
left_shift // <<
right_shift // >>
unsigned_right_shift // >>>
@ -271,8 +270,7 @@ fn build_token_str() []string {
s[Kind.nl] = 'NLL'
s[Kind.dollar] = '$'
s[Kind.at] = '@'
s[Kind.str_dollar] = 'string interpolation1'
s[Kind.str_lcbr] = 'string interpolation2'
s[Kind.str_dollar] = '$2'
s[Kind.key_assert] = 'assert'
s[Kind.key_struct] = 'struct'
s[Kind.key_if] = 'if'
@ -543,7 +541,6 @@ pub fn kind_to_string(k Kind) string {
.dollar { 'dollar' }
.at { 'at' }
.str_dollar { 'str_dollar' }
.str_lcbr { 'str_lcbr' }
.left_shift { 'left_shift' }
.right_shift { 'right_shift' }
.unsigned_right_shift { 'unsigned_right_shift' }
@ -666,7 +663,6 @@ pub fn kind_from_string(s string) !Kind {
'dollar' { .dollar }
'at' { .at }
'str_dollar' { .str_dollar }
'str_lcbr' { .str_lcbr }
'left_shift' { .left_shift }
'right_shift' { .right_shift }
'unsigned_right_shift' { .unsigned_right_shift }