Skip to content

Commit

Permalink
runtime(python): Add f-string support
Browse files Browse the repository at this point in the history
Fixes #14033.
  • Loading branch information
dkearns committed Feb 20, 2024
1 parent fcaed6a commit 55c39a5
Show file tree
Hide file tree
Showing 37 changed files with 1,394 additions and 10 deletions.
91 changes: 81 additions & 10 deletions runtime/syntax/python.vim
Original file line number Diff line number Diff line change
Expand Up @@ -122,18 +122,18 @@ syn match pythonDecoratorName "@\s*\h\%(\w\|\.\)*" display contains=pythonDeco
" Single line multiplication.
syn match pythonMatrixMultiply
\ "\%(\w\|[])]\)\s*@"
\ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonFunction,pythonDoctestValue
\ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonFunction,pythonDoctestValue,@pythonFStringContained
\ transparent
" Multiplication continued on the next line after backslash.
syn match pythonMatrixMultiply
\ "[^\\]\\\s*\n\%(\s*\.\.\.\s\)\=\s\+@"
\ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonFunction,pythonDoctestValue
\ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonFunction,pythonDoctestValue,@pythonFStringContained
\ transparent
" Multiplication in a parenthesized expression over multiple lines with @ at
" the start of each continued line; very similar to decorators and complex.
syn match pythonMatrixMultiply
\ "^\s*\%(\%(>>>\|\.\.\.\)\s\+\)\=\zs\%(\h\|\%(\h\|[[(]\).\{-}\%(\w\|[])]\)\)\s*\n\%(\s*\.\.\.\s\)\=\s\+@\%(.\{-}\n\%(\s*\.\.\.\s\)\=\s\+@\)*"
\ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonFunction,pythonDoctestValue
\ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonFunction,pythonDoctestValue,@pythonFStringContained
\ transparent

syn match pythonFunction "\h\w*" display contained
Expand All @@ -143,25 +143,92 @@ syn keyword pythonTodo FIXME NOTE NOTES TODO XXX contained

" Triple-quoted strings can contain doctests.
syn region pythonString matchgroup=pythonQuotes
\ start=+[uU]\=\z(['"]\)+ end="\z1" skip="\\\\\|\\\z1"
\ start=+[uUbB]\=\z(['"]\)+ end="$\|\z1" skip="\\\\\|\\\z1"
\ contains=pythonEscape,@Spell
syn region pythonString matchgroup=pythonTripleQuotes
\ start=+[uU]\=\z('''\|"""\)+ end="\z1" keepend
\ start=+[uUbB]\=\z('''\|"""\)+ end="\z1" keepend
\ contains=pythonEscape,pythonSpaceError,pythonDoctest,@Spell
syn region pythonRawString matchgroup=pythonQuotes
\ start=+[uU]\=[rR]\z(['"]\)+ end="\z1" skip="\\\\\|\\\z1"
\ start=+\%([bB][rR]\=\|[rR][bB]\=\)\z(['"]\)+
\ end="$\|\z1" skip="\\\\\|\\\r\=$\|\\\z1"
\ contains=@Spell
syn region pythonRawString matchgroup=pythonTripleQuotes
\ start=+[uU]\=[rR]\z('''\|"""\)+ end="\z1" keepend
\ start=+\%([bB][rR]\=\|[rR][bB]\=\)\z('''\|"""\)+
\ end="\z1" keepend
\ contains=pythonSpaceError,pythonDoctest,@Spell
syn region pythonFString matchgroup=pythonQuotes
\ start=+[fF]\z(['"]\)+
\ end="$\|\z1" skip="\\\\\|\\\z1"
\ contains=pythonEscape,pythonFStringEscapedBrace,pythonFStringReplacement,@Spell
syn region pythonFString matchgroup=pythonTripleQuotes
\ start=+[fF]\z('''\|"""\)+
\ end="\z1" keepend
\ contains=pythonEscape,pythonSpaceError,pythonFStringEscapedBrace,pythonFStringReplacement,pythonDoctest,@Spell
syn region pythonRawFString matchgroup=pythonQuotes
\ start=+\%([fF][rR]\|[rR][fF]\)\z(['"]\)+
\ end="$\|\z1" skip="\\\\\|\\\r\=$\|\\\z1"
\ contains=pythonFStringEscapedBrace,pythonFStringReplacement,@Spell
syn region pythonRawFString matchgroup=pythonTripleQuotes
\ start=+\%([fF][rR]\|[rR][fF]\)\z('''\|"""\)+
\ end="\z1" keepend
\ contains=pythonSpaceError,pythonFStringEscapedBrace,pythonFStringReplacement,pythonDoctest,@Spell

syn match pythonEscape +\\[abfnrtv'"\\]+ contained
syn match pythonEscape "\\\o\{1,3}" contained
syn match pythonEscape "\\x\x\{2}" contained
syn match pythonEscape "\%(\\u\x\{4}\|\\U\x\{8}\)" contained
" Python allows case-insensitive Unicode IDs: http://www.unicode.org/charts/
syn match pythonEscape "\\N{\a\+\%(\s\a\+\)*}" contained
syn match pythonEscape "\\$"
syn match pythonEscape "\\\r\=$"

syn region pythonFStringReplacement matchgroup=pythonFStringBrace start=+{+ end=+}+ contained contains=pythonFStringExpression

" Skip contained '[:!]'
" TODO: this should contain @pythonExpression rather than TOP
syn region pythonFStringBrackets
\ start="{" end="}"
\ contained contains=TOP
\ transparent
syn region pythonFStringBrackets
\ start="(" end=")"
\ contained contains=TOP
\ transparent
syn region pythonFStringBrackets
\ start="\[" end="]"
\ contained contains=TOP
\ transparent

syn region pythonFStringReplacementWhitespace start="\s" end="\ze\S" contained nextgroup=pythonFStringConversion,pythonFStringFormatSpec

" TODO: contains (yield_expr | star_expressions)
syn cluster pythonExpression
\ contains=pythonNumber,python.*String,pythonBuiltin,pythonFStringBrackets,pythonComment

syn region pythonFStringExpression
\ start="." end="\ze[=!:}]"
\ contained contains=@pythonExpression
\ nextgroup=pythonFStringEquals,pythonFStringConversion,pythonFStringFormatSpec

syn match pythonFStringEquals "="
\ contained
\ nextgroup=pythonFStringConversion,pythonFStringFormatSpec,pythonFStringReplacementWhitespace,pythonComment
\ skipwhite skipempty
hi def link pythonFStringEquals Special

syn match pythonFStringConversion "![ars]"
\ contained
\ nextgroup=pythonFStringFormatSpec,pythonFStringReplacementWhitespace,pythonComment
\ skipwhite skipempty
hi def link pythonFStringConversion Special

syn region pythonFStringFormatSpec
\ matchgroup=Delimiter start=":" matchgroup=NONE end="\ze}"
\ contained contains=pythonFStringReplacement
hi def link pythonFStringFormatSpec Special

syn match pythonFStringEscapedBrace "{{\|}}" contained

syn cluster pythonFStringContained contains=pythonFString.\+

" It is very important to understand all details before changing the
" regular expressions below or their order.
Expand Down Expand Up @@ -226,7 +293,7 @@ if !exists("python_no_builtin_highlight")
syn keyword pythonBuiltin tuple type vars zip __import__
" avoid highlighting attributes as builtins
syn match pythonAttribute /\.\h\w*/hs=s+1
\ contains=ALLBUT,pythonBuiltin,pythonFunction,pythonAsync
\ contains=ALLBUT,pythonBuiltin,pythonFunction,pythonAsync,@pythonFStringContained
\ transparent
endif

Expand Down Expand Up @@ -283,7 +350,7 @@ if !exists("python_no_doctest_highlight")
if !exists("python_no_doctest_code_highlight")
syn region pythonDoctest
\ start="^\s*>>>\s" end="^\s*$"
\ contained contains=ALLBUT,pythonDoctest,pythonFunction,@Spell
\ contained contains=ALLBUT,pythonDoctest,pythonFunction,@pythonFStringContained,@Spell
syn region pythonDoctestValue
\ start=+^\s*\%(>>>\s\|\.\.\.\s\|"""\|'''\)\@!\S\++ end="$"
\ contained
Expand Down Expand Up @@ -312,9 +379,13 @@ hi def link pythonComment Comment
hi def link pythonTodo Todo
hi def link pythonString String
hi def link pythonRawString String
hi def link pythonFString String
hi def link pythonRawFString String
hi def link pythonQuotes String
hi def link pythonTripleQuotes pythonQuotes
hi def link pythonEscape Special
hi def link pythonFStringEscapedBrace Special
hi def link pythonFStringBrace Include
if !exists("python_no_number_highlight")
hi def link pythonNumber Number
endif
Expand Down
20 changes: 20 additions & 0 deletions runtime/syntax/testdir/dumps/python_fstring_00.dump
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
>#+0#0000e05#ffffff0| |P|y|t|h|o|n| |f|-|s|t|r|i|n|g| |t|e|s|t|s| +0#0000000&@51
@75
|#+0#0000e05&| |P|y|t|h|o|n|-|3|.|1|2|.|2|/|L|i|b|/|t|e|s|t|/|t|e|s|t|_|f|s|t|r|i|n|g|.|p|y| |(|r|e|f|o|r|m|a|t@1|e|d| |f|o|r| |s|y|n|t|a|x| |t|e|s|t|i|n|g|)| +0#0000000&@1
@75
|#+0#0000e05&@1| |t|e|s|t|_|a|s|t| +0#0000000&@63
|f+0#e000002&|'|{+0#e000e06&|a+0#0000000&| |*| |x|(|)|}+0#e000e06&|'+0#e000002&| +0#0000000&@62
@75
|#+0#0000e05&@1| |t|e|s|t|_|a|s|t|_|l|i|n|e|_|n|u|m|b|e|r|s|_|m|u|l|t|i|p|l|e|_|f|o|r|m|a|t@1|e|d|v|a|l|u|e|s| +0#0000000&@25
|f+0#e000002&|'|n|o| |f|o|r|m|a|t@1|e|d| |v|a|l|u|e|s|'| +0#0000000&@52
|f+0#e000002&|'|e|g@1|s| |{+0#e000e06&|a+0#0000000&| |*| |x|(|)|}+0#e000e06&| +0#e000002&|s|p|a|m| |{+0#e000e06&|b+0#0000000&| |+| |y|(|)|}+0#e000e06&|'+0#e000002&| +0#0000000&@42
@75
|#+0#0000e05&@1| |t|e|s|t|_|a|s|t|_|l|i|n|e|_|n|u|m|b|e|r|s|_|n|e|s|t|e|d| +0#0000000&@43
|f+0#e000002&|'|{+0#e000e06&|a+0#0000000&| |*| |f+0#e000002&|"|-|{+0#e000e06&|x+0#0000000&|(|)|}+0#e000e06&|-+0#e000002&|"|}+0#e000e06&|'+0#e000002&| +0#0000000&@55
@75
|#+0#0000e05&@1| |t|e|s|t|_|a|s|t|_|l|i|n|e|_|n|u|m|b|e|r|s|_|d|u|p|l|i|c|a|t|e|_|e|x|p|r|e|s@1|i|o|n| +0#0000000&@29
|f+0#e000002&|'|{+0#e000e06&|a+0#0000000&| |*| |x|(|)|}+0#e000e06&| +0#e000002&|{+0#e000e06&|a+0#0000000&| |*| |x|(|)|}+0#e000e06&| +0#e000002&|{+0#e000e06&|a+0#0000000&| |*| |x|(|)|}+0#e000e06&|'+0#e000002&| +0#0000000&@42
@75
|#+0#0000e05&@1| |t|e|s|t|_|a|s|t|_|n|u|m|b|e|r|s|_|f|s|t|r|i|n|g|_|w|i|t|h|_|f|o|r|m|a|t@1|i|n|g| +0#0000000&@31
|'+0#e000002&|f|"|H|e|r|e| |i|s| |t|h|a|t| |p|e|s|k|y| |{|x@2|:|.|3|f|}| |a|g|a|i|n|"|'| +0#0000000&@35
|"|i|n|p|u|t|/|p|y|t|h|o|n|_|f|s|t|r|i|n|g|.|p|y|"| |6|1|3|L|,| |1|3|0|2|4|B| @18|1|,|1| @10|T|o|p|
20 changes: 20 additions & 0 deletions runtime/syntax/testdir/dumps/python_fstring_01.dump
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
| +0&#ffffff0@74
|#+0#0000e05&@1| |t|e|s|t|_|a|s|t|_|l|i|n|e|_|n|u|m|b|e|r|s|_|d|u|p|l|i|c|a|t|e|_|e|x|p|r|e|s@1|i|o|n| +0#0000000&@29
|f+0#e000002&|'|{+0#e000e06&|a+0#0000000&| |*| |x|(|)|}+0#e000e06&| +0#e000002&|{+0#e000e06&|a+0#0000000&| |*| |x|(|)|}+0#e000e06&| +0#e000002&|{+0#e000e06&|a+0#0000000&| |*| |x|(|)|}+0#e000e06&|'+0#e000002&| +0#0000000&@42
@75
|#+0#0000e05&@1| |t|e|s|t|_|a|s|t|_|n|u|m|b|e|r|s|_|f|s|t|r|i|n|g|_|w|i|t|h|_|f|o|r|m|a|t@1|i|n|g| +0#0000000&@31
>'+0#e000002&|f|"|H|e|r|e| |i|s| |t|h|a|t| |p|e|s|k|y| |{|x@2|:|.|3|f|}| |a|g|a|i|n|"|'| +0#0000000&@35
@75
|#+0#0000e05&@1| |t|e|s|t|_|a|s|t|_|l|i|n|e|_|n|u|m|b|e|r|s|_|m|u|l|t|i|l|i|n|e|_|f|s|t|r|i|n|g| +0#0000000&@32
|f+0#e000002&|'@2| +0#0000000&@70
| +0#e000002&@1|{+0#e000e06&|a+0#0000000&| @70
@5|*| @68
@7|x|(|)|}+0#e000e06&| +0#0000000&@63
|n+0#e000002&|o|n|-|i|m|p|o|r|t|a|n|t| |c|o|n|t|e|n|t| +0#0000000&@53
|'+0#e000002&@2| +0#0000000&@71
@75
|f+0#e000002&|'@2| +0#0000000&@70
| +0#e000002&@9|{+0#e000e06&|b+0#0000000&|l|e|c|h|}+0#e000e06&| +0#0000000&@57
|'+0#e000002&@2| +0#0000000&@71
@75
@57|1|9|,|1| @10|2|%|
20 changes: 20 additions & 0 deletions runtime/syntax/testdir/dumps/python_fstring_02.dump
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
| +0&#ffffff0@74
|#+0#0000e05&@1| |t|e|s|t|_|a|s|t|_|l|i|n|e|_|n|u|m|b|e|r|s|_|w|i|t|h|_|p|a|r|e|n|t|h|e|s|e|s| +0#0000000&@33
|x| |=| |(| @69
@4|f+0#e000002&|"| |{+0#e000e06&|t+0#0000000&|e|s|t|(|t|)|}+0#e000e06&|"+0#e000002&| +0#0000000&@57
|)| @73
> @74
|x| |=| |(| @69
@4|u+0#e000002&|'|w|a|t|'|,+0#0000000&| @63
@4|u+0#e000002&|"|w|a|t|"|,+0#0000000&| @63
@4|b+0#e000002&|'|w|a|t|'|,+0#0000000&| @63
@4|b+0#e000002&|"|w|a|t|"|,+0#0000000&| @63
@4|f+0#e000002&|'|w|a|t|'|,+0#0000000&| @63
@4|f+0#e000002&|"|w|a|t|"|,+0#0000000&| @63
|)| @73
@75
|y| |=| |(| @69
@4|u+0#e000002&|'@2|w|a|t|'@2|,+0#0000000&| @59
@4|u+0#e000002&|"@2|w|a|t|"@2|,+0#0000000&| @59
@4|b+0#e000002&|'@2|w|a|t|'@2|,+0#0000000&| @59
@57|3|7|,|0|-|1| @8|5|%|
20 changes: 20 additions & 0 deletions runtime/syntax/testdir/dumps/python_fstring_03.dump
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
| +0&#ffffff0@3|b+0#e000002&|'@2|w|a|t|'@2|,+0#0000000&| @59
@4|b+0#e000002&|"@2|w|a|t|"@2|,+0#0000000&| @59
@4|f+0#e000002&|'@2|w|a|t|'@2|,+0#0000000&| @59
@4|f+0#e000002&|"@2|w|a|t|"@2|,+0#0000000&| @59
|)| @73
> @74
|x| |=| |(| @69
@8|'+0#e000002&|P|E|R|L|_|M@1|_|O|P|T|'|,+0#0000000&| |(| @50
@12|f+0#e000002&|'|w|a|t|'| +0#0000000&@56
@12|f+0#e000002&|'|s|o|m|e|_|s|t|r|i|n|g|=|{+0#e000e06&|f+0#0000000&|(|x|)|}+0#e000e06&| +0#e000002&|'| +0#0000000&@40
@12|f+0#e000002&|'|w|a|t|'| +0#0000000&@56
@8|)|,| @64
|)| @73
@75
|#+0#0000e05&@1| |t|e|s|t|_|a|s|t|_|f|s|t|r|i|n|g|_|e|m|p|t|y|_|f|o|r|m|a|t|_|s|p|e|c| +0#0000000&@37
|f+0#e000002&|'|{+0#e000e06&|e+0#0000000&|x|p|r|:+0#e000e06&|}|'+0#e000002&| +0#0000000&@64
@75
@75
|#+0#0000e05&@1| |t|e|s|t|_|d|o|c|s|t|r|i|n|g| +0#0000000&@57
@57|5@1|,|0|-|1| @8|8|%|
20 changes: 20 additions & 0 deletions runtime/syntax/testdir/dumps/python_fstring_04.dump
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
|#+0#0000e05#ffffff0@1| |t|e|s|t|_|d|o|c|s|t|r|i|n|g| +0#0000000&@57
|d+0#af5f00255&|e|f| +0#0000000&|f+0#00e0e07&|(+0#0000000&|)|:| @66
@4|f+0#e000002&|'@2|N|o|t| |a| |d|o|c|s|t|r|i|n|g|'@2| +0#0000000&@48
@75
|d+0#af5f00255&|e|f| +0#0000000&|g+0#00e0e07&|(+0#0000000&|)|:| @66
@4>'+0#e000002&@2|N|o|t| |a| |d|o|c|s|t|r|i|n|g|'@2| +0#0000000&|\+0#e000e06&| +0#0000000&@47
@4|f+0#e000002&|'@1| +0#0000000&@67
@75
@75
|#+0#0000e05&@1| |t|e|s|t|_|a|s|t|_|c|o|m|p|i|l|e|_|t|i|m|e|_|c|o|n|c|a|t| +0#0000000&@43
|(|'+0#e000002&|f|o@1|'| +0#0000000&|f+0#e000002&|'|{+0#e000e06&|3+0#e000002&|}+0#e000e06&|'+0#e000002&|,+0#0000000&| |'+0#e000002&|f|o@1|3|'|)+0#0000000&| @52
@75
|#+0#0000e05&@1| |t|e|s|t|_|l|i|t|e|r|a|l| +0#0000000&@59
|(|f+0#e000002&|'@1|,+0#0000000&| |'+0#e000002&@1|)+0#0000000&| @65
|(|f+0#e000002&|'|a|'|,+0#0000000&| |'+0#e000002&|a|'|)+0#0000000&| @63
|(|f+0#e000002&|'| |'|,+0#0000000&| |'+0#e000002&| |'|)+0#0000000&| @63
@75
|#+0#0000e05&@1| |t|e|s|t|_|d|o|u|b|l|e|_|b|r|a|c|e|s| +0#0000000&@53
|(|f+0#e000002&|'|{+0#e000e06&@1|'+0#e000002&|,+0#0000000&| |'+0#e000002&|{|'|)+0#0000000&| @62
@57|7|3|,|5| @9|1@1|%|
20 changes: 20 additions & 0 deletions runtime/syntax/testdir/dumps/python_fstring_05.dump
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
|(+0&#ffffff0|f+0#e000002&|'|{+0#e000e06&@1|'+0#e000002&|,+0#0000000&| |'+0#e000002&|{|'|)+0#0000000&| @62
|(|f+0#e000002&|'|a|{+0#e000e06&@1|'+0#e000002&|,+0#0000000&| |'+0#e000002&|a|{|'|)+0#0000000&| @60
|(|f+0#e000002&|'|{+0#e000e06&@1|b+0#e000002&|'|,+0#0000000&| |'+0#e000002&|{|b|'|)+0#0000000&| @60
|(|f+0#e000002&|'|a|{+0#e000e06&@1|b+0#e000002&|'|,+0#0000000&| |'+0#e000002&|a|{|b|'|)+0#0000000&| @58
|(|f+0#e000002&|'|}+0#e000e06&@1|'+0#e000002&|,+0#0000000&| |'+0#e000002&|}|'|)+0#0000000&| @62
>(|f+0#e000002&|'|a|}+0#e000e06&@1|'+0#e000002&|,+0#0000000&| |'+0#e000002&|a|}|'|)+0#0000000&| @60
|(|f+0#e000002&|'|}+0#e000e06&@1|b+0#e000002&|'|,+0#0000000&| |'+0#e000002&|}|b|'|)+0#0000000&| @60
|(|f+0#e000002&|'|a|}+0#e000e06&@1|b+0#e000002&|'|,+0#0000000&| |'+0#e000002&|a|}|b|'|)+0#0000000&| @58
|(|f+0#e000002&|'|{+0#e000e06&@1|}@1|'+0#e000002&|,+0#0000000&| |'+0#e000002&|{|}|'|)+0#0000000&| @59
|(|f+0#e000002&|'|a|{+0#e000e06&@1|}@1|'+0#e000002&|,+0#0000000&| |'+0#e000002&|a|{|}|'|)+0#0000000&| @57
|(|f+0#e000002&|'|{+0#e000e06&@1|b+0#e000002&|}+0#e000e06&@1|'+0#e000002&|,+0#0000000&| |'+0#e000002&|{|b|}|'|)+0#0000000&| @57
|(|f+0#e000002&|'|{+0#e000e06&@1|}@1|c+0#e000002&|'|,+0#0000000&| |'+0#e000002&|{|}|c|'|)+0#0000000&| @57
|(|f+0#e000002&|'|a|{+0#e000e06&@1|b+0#e000002&|}+0#e000e06&@1|'+0#e000002&|,+0#0000000&| |'+0#e000002&|a|{|b|}|'|)+0#0000000&| @55
|(|f+0#e000002&|'|a|{+0#e000e06&@1|}@1|c+0#e000002&|'|,+0#0000000&| |'+0#e000002&|a|{|}|c|'|)+0#0000000&| @55
|(|f+0#e000002&|'|{+0#e000e06&@1|b+0#e000002&|}+0#e000e06&@1|c+0#e000002&|'|,+0#0000000&| |'+0#e000002&|{|b|}|c|'|)+0#0000000&| @55
|(|f+0#e000002&|'|a|{+0#e000e06&@1|b+0#e000002&|}+0#e000e06&@1|c+0#e000002&|'|,+0#0000000&| |'+0#e000002&|a|{|b|}|c|'|)+0#0000000&| @53
@75
|(|f+0#e000002&|'|{+0#e000e06&@2|1+0#e000002&|0|}+0#e000e06&|'+0#e000002&|,+0#0000000&| |'+0#e000002&|{|1|0|'|)+0#0000000&| @56
|(|f+0#e000002&|'|}+0#e000e06&@1|{|1+0#e000002&|0|}+0#e000e06&|'+0#e000002&|,+0#0000000&| |'+0#e000002&|}|1|0|'|)+0#0000000&| @56
@57|9|1|,|1| @9|1|4|%|
20 changes: 20 additions & 0 deletions runtime/syntax/testdir/dumps/python_fstring_06.dump
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
|(+0&#ffffff0|f+0#e000002&|'|}+0#e000e06&@1|{|1+0#e000002&|0|}+0#e000e06&|'+0#e000002&|,+0#0000000&| |'+0#e000002&|}|1|0|'|)+0#0000000&| @56
|(|f+0#e000002&|'|}+0#e000e06&@1|{@2|1+0#e000002&|0|}+0#e000e06&|'+0#e000002&|,+0#0000000&| |'+0#e000002&|}|{|1|0|'|)+0#0000000&| @53
|(|f+0#e000002&|'|}+0#e000e06&@1|a+0#e000002&|{+0#e000e06&@2|1+0#e000002&|0|}+0#e000e06&|'+0#e000002&|,+0#0000000&| |'+0#e000002&|}|a|{|1|0|'|)+0#0000000&| @51
@75
|(|f+0#e000002&|'|{+0#e000e06&|1+0#e000002&|0|}+0#e000e06&|{@1|'+0#e000002&|,+0#0000000&| |'+0#e000002&|1|0|{|'|)+0#0000000&| @56
>(|f+0#e000002&|'|{+0#e000e06&|1+0#e000002&|0|}+0#e000e06&@2|'+0#e000002&|,+0#0000000&| |'+0#e000002&|1|0|}|'|)+0#0000000&| @56
|(|f+0#e000002&|'|{+0#e000e06&|1+0#e000002&|0|}+0#e000e06&@2|{@1|'+0#e000002&|,+0#0000000&| |'+0#e000002&|1|0|}|{|'|)+0#0000000&| @53
|(|f+0#e000002&|'|{+0#e000e06&|1+0#e000002&|0|}+0#e000e06&@2|a+0#e000002&|{+0#e000e06&@1|'+0#e000002&| +0#0000000&|'+0#e000002&|}|'|,+0#0000000&| |'+0#e000002&|1|0|}|a|{|}|'|)+0#0000000&| @46
@75
|#+0#0000e05&| |I|n|s|i|d|e| |o|f| |s|t|r|i|n|g|s|,| |d|o|n|'|t| |i|n|t|e|r|p|r|e|t| |d|o|u|b|l|e|d| |b|r|a|c|k|e|t|s|.| +0#0000000&@20
|(|f+0#e000002&|'|{+0#e000e06&|"+0#e000002&|{@1|}@1|"|}+0#e000e06&|'+0#e000002&|,+0#0000000&| |'+0#e000002&|{@1|}@1|'|)+0#0000000&| @53
@75
|#+0#0000e05&@1| |t|e|s|t|_|c|o|m|p|i|l|e|_|t|i|m|e|_|c|o|n|c|a|t| +0#0000000&@47
|x| |=| |'+0#e000002&|d|e|f|'| +0#0000000&@65
|(|'+0#e000002&|a|b|c|'| +0#0000000&|f+0#e000002&|'|#@1| |{+0#e000e06&|x+0#0000000&|}+0#e000e06&|g+0#e000002&|h|i|'|,+0#0000000&| |'+0#e000002&|a|b|c|#@1| |d|e|f|g|h|i|'|)+0#0000000&| @38
|(|'+0#e000002&|a|b|c|'| +0#0000000&|f+0#e000002&|'|{+0#e000e06&|x+0#0000000&|}+0#e000e06&|'+0#e000002&| +0#0000000&|'+0#e000002&|g|h|i|'|,+0#0000000&| |'+0#e000002&|a|b|c|d|e|f|g|h|i|'|)+0#0000000&| @41
|(|'+0#e000002&|a|b|c|'| +0#0000000&|f+0#e000002&|'|{+0#e000e06&|x+0#0000000&|}+0#e000e06&|'+0#e000002&| +0#0000000&|'+0#e000002&|g|h|'| +0#0000000&|f+0#e000002&|'|i|{+0#e000e06&|x+0#0000000&|:+0#e000e06&|4|}|'+0#e000002&|,+0#0000000&| |'+0#e000002&|a|b|c|d|e|f|g|h|i|d|e|f| |'|)+0#0000000&| @28
|(|'+0#e000002&|{|x|}|'| +0#0000000&|f+0#e000002&|'|{+0#e000e06&|x+0#0000000&|}+0#e000e06&|'+0#e000002&|,+0#0000000&| |'+0#e000002&|{|x|}|d|e|f|'|)+0#0000000&| @50
|(|'+0#e000002&|{|x|'| +0#0000000&|f+0#e000002&|'|{+0#e000e06&|x+0#0000000&|}+0#e000e06&|'+0#e000002&|,+0#0000000&| |'+0#e000002&|{|x|d|e|f|'|)+0#0000000&| @52
@57|1|0|9|,|1| @8|1|7|%|
20 changes: 20 additions & 0 deletions runtime/syntax/testdir/dumps/python_fstring_07.dump
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
|(+0&#ffffff0|'+0#e000002&|{|x|'| +0#0000000&|f+0#e000002&|'|{+0#e000e06&|x+0#0000000&|}+0#e000e06&|'+0#e000002&|,+0#0000000&| |'+0#e000002&|{|x|d|e|f|'|)+0#0000000&| @52
|(|'+0#e000002&|{|x|}|'| +0#0000000&|f+0#e000002&|'|{+0#e000e06&|x+0#0000000&|}+0#e000e06&|'+0#e000002&|,+0#0000000&| |'+0#e000002&|{|x|}|d|e|f|'|)+0#0000000&| @50
|(|'+0#e000002&|{@1|x|}@1|'| +0#0000000&|f+0#e000002&|'|{+0#e000e06&|x+0#0000000&|}+0#e000e06&|'+0#e000002&|,+0#0000000&| |'+0#e000002&|{@1|x|}@1|d|e|f|'|)+0#0000000&| @46
|(|'+0#e000002&|{@1|x|'| +0#0000000&|f+0#e000002&|'|{+0#e000e06&|x+0#0000000&|}+0#e000e06&|'+0#e000002&|,+0#0000000&| |'+0#e000002&|{@1|x|d|e|f|'|)+0#0000000&| @50
|(|'+0#e000002&|x|}@1|'| +0#0000000&|f+0#e000002&|'|{+0#e000e06&|x+0#0000000&|}+0#e000e06&|'+0#e000002&|,+0#0000000&| |'+0#e000002&|x|}@1|d|e|f|'|)+0#0000000&| @50
>(|f+0#e000002&|'|{+0#e000e06&|x+0#0000000&|}+0#e000e06&|'+0#e000002&| +0#0000000&|'+0#e000002&|x|}@1|'|,+0#0000000&| |'+0#e000002&|d|e|f|x|}@1|'|)+0#0000000&| @50
|(|f+0#e000002&|'|{+0#e000e06&|x+0#0000000&|}+0#e000e06&|'+0#e000002&| +0#0000000&|'+0#e000002&@1|,+0#0000000&| |'+0#e000002&|d|e|f|'|)+0#0000000&| @56
|(|'+0#e000002&@1| +0#0000000&|f+0#e000002&|'|{+0#e000e06&|x+0#0000000&|}+0#e000e06&|'+0#e000002&| +0#0000000&|'+0#e000002&@1|,+0#0000000&| |'+0#e000002&|d|e|f|'|)+0#0000000&| @53
|(|'+0#e000002&@1| +0#0000000&|f+0#e000002&|'|{+0#e000e06&|x+0#0000000&|}+0#e000e06&|'+0#e000002&|,+0#0000000&| |'+0#e000002&|d|e|f|'|)+0#0000000&| @56
|(|f+0#e000002&|'|{+0#e000e06&|x+0#0000000&|}+0#e000e06&|'+0#e000002&| +0#0000000&|'+0#e000002&|2|'|,+0#0000000&| |'+0#e000002&|d|e|f|2|'|)+0#0000000&| @54
|(|'+0#e000002&|1|'| +0#0000000&|f+0#e000002&|'|{+0#e000e06&|x+0#0000000&|}+0#e000e06&|'+0#e000002&| +0#0000000&|'+0#e000002&|2|'|,+0#0000000&| |'+0#e000002&|1|d|e|f|2|'|)+0#0000000&| @49
|(|'+0#e000002&|1|'| +0#0000000&|f+0#e000002&|'|{+0#e000e06&|x+0#0000000&|}+0#e000e06&|'+0#e000002&|,+0#0000000&| |'+0#e000002&|1|d|e|f|'|)+0#0000000&| @54
|(|f+0#e000002&|'|{+0#e000e06&|x+0#0000000&|}+0#e000e06&|'+0#e000002&| +0#0000000&|f+0#e000002&|'|-|{+0#e000e06&|x+0#0000000&|}+0#e000e06&|'+0#e000002&|,+0#0000000&| |'+0#e000002&|d|e|f|-|d|e|f|'|)+0#0000000&| @47
|(|'+0#e000002&@1| +0#0000000&|f+0#e000002&|'@1|,+0#0000000&| |'+0#e000002&@1|)+0#0000000&| @62
|(|'+0#e000002&@1| +0#0000000&|f+0#e000002&|'@1| +0#0000000&|'+0#e000002&@1|,+0#0000000&| |'+0#e000002&@1|)+0#0000000&| @59
|(|'+0#e000002&@1| +0#0000000&|f+0#e000002&|'@1| +0#0000000&|'+0#e000002&@1| +0#0000000&|f+0#e000002&|'@1|,+0#0000000&| |'+0#e000002&@1|)+0#0000000&| @55
|(|f+0#e000002&|'@1|,+0#0000000&| |'+0#e000002&@1|)+0#0000000&| @65
|(|f+0#e000002&|'@1| +0#0000000&|'+0#e000002&@1|,+0#0000000&| |'+0#e000002&@1|)+0#0000000&| @62
|(|f+0#e000002&|'@1| +0#0000000&|'+0#e000002&@1| +0#0000000&|f+0#e000002&|'@1|,+0#0000000&| |'+0#e000002&@1|)+0#0000000&| @58
@57|1|2|7|,|1| @8|2|0|%|

0 comments on commit 55c39a5

Please sign in to comment.