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:
parent
7830597b66
commit
dd5f6186a1
@ -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
|
||||
|
@ -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('{')
|
||||
|
@ -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}'
|
||||
| ^
|
||||
|
@ -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}'
|
||||
}
|
||||
|
@ -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('{')
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +0,0 @@
|
||||
Foo = def
|
||||
Foo = def
|
@ -1,9 +0,0 @@
|
||||
enum Foo {
|
||||
abc
|
||||
def
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println('Foo = {Foo.def}')
|
||||
println('Foo = {unsafe { Foo(1) }}')
|
||||
}
|
@ -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(' ')})'
|
||||
}
|
||||
}
|
||||
}
|
@ -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 }
|
||||
|
Loading…
Reference in New Issue
Block a user