Skip to content

Commit 0b45b5f

Browse files
committed
Fix FORMAT_VALUE for values that have both a conversion and a format_spec.
Also output the conversion and flags in disassembly.
1 parent 6ad3ceb commit 0b45b5f

File tree

7 files changed

+38
-34
lines changed

7 files changed

+38
-34
lines changed

ASTNode.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,9 @@ class ASTFormattedValue : public ASTNode {
689689
STR = 1,
690690
REPR = 2,
691691
ASCII = 3,
692-
FMTSPEC = 4
692+
CONVERSION_MASK = 0x03,
693+
694+
HAVE_FMT_SPEC = 4,
693695
};
694696

695697
ASTFormattedValue(PycRef<ASTNode> val, ConversionFlag conversion,

ASTree.cpp

Lines changed: 14 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -978,29 +978,14 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
978978
case Pyc::FORMAT_VALUE_A:
979979
{
980980
auto conversion_flag = static_cast<ASTFormattedValue::ConversionFlag>(operand);
981-
switch (conversion_flag) {
982-
case ASTFormattedValue::ConversionFlag::NONE:
983-
case ASTFormattedValue::ConversionFlag::STR:
984-
case ASTFormattedValue::ConversionFlag::REPR:
985-
case ASTFormattedValue::ConversionFlag::ASCII:
986-
{
987-
auto val = stack.top();
988-
stack.pop();
989-
stack.push(new ASTFormattedValue(val, conversion_flag, nullptr));
990-
}
991-
break;
992-
case ASTFormattedValue::ConversionFlag::FMTSPEC:
993-
{
994-
auto format_spec = stack.top();
995-
stack.pop();
996-
auto val = stack.top();
997-
stack.pop();
998-
stack.push(new ASTFormattedValue(val, conversion_flag, format_spec));
999-
}
1000-
break;
1001-
default:
1002-
fprintf(stderr, "Unsupported FORMAT_VALUE_A conversion flag: %d\n", operand);
981+
PycRef<ASTNode> format_spec = nullptr;
982+
if (conversion_flag & ASTFormattedValue::HAVE_FMT_SPEC) {
983+
format_spec = stack.top();
984+
stack.pop();
1003985
}
986+
auto val = stack.top();
987+
stack.pop();
988+
stack.push(new ASTFormattedValue(val, conversion_flag, format_spec));
1004989
}
1005990
break;
1006991
case Pyc::GET_AWAITABLE:
@@ -2659,23 +2644,21 @@ void print_formatted_value(PycRef<ASTFormattedValue> formatted_value, PycModule*
26592644
pyc_output << "{";
26602645
print_src(formatted_value->val(), mod, pyc_output);
26612646

2662-
switch (formatted_value->conversion()) {
2663-
case ASTFormattedValue::ConversionFlag::NONE:
2647+
switch (formatted_value->conversion() & ASTFormattedValue::CONVERSION_MASK) {
2648+
case ASTFormattedValue::NONE:
26642649
break;
2665-
case ASTFormattedValue::ConversionFlag::STR:
2650+
case ASTFormattedValue::STR:
26662651
pyc_output << "!s";
26672652
break;
2668-
case ASTFormattedValue::ConversionFlag::REPR:
2653+
case ASTFormattedValue::REPR:
26692654
pyc_output << "!r";
26702655
break;
2671-
case ASTFormattedValue::ConversionFlag::ASCII:
2656+
case ASTFormattedValue::ASCII:
26722657
pyc_output << "!a";
26732658
break;
2674-
case ASTFormattedValue::ConversionFlag::FMTSPEC:
2659+
}
2660+
if (formatted_value->conversion() & ASTFormattedValue::HAVE_FMT_SPEC) {
26752661
pyc_output << ":" << formatted_value->format_spec().cast<ASTObject>()->object().cast<PycString>()->value();
2676-
break;
2677-
default:
2678-
fprintf(stderr, "Unsupported NODE_FORMATTEDVALUE conversion flag: %d\n", formatted_value->conversion());
26792662
}
26802663
pyc_output << "}";
26812664
}

bytecode.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,11 @@ void bc_disasm(std::ostream& pyc_output, PycRef<PycCode> code, PycModule* mod,
331331
};
332332
static const size_t intrinsic2_names_len = sizeof(intrinsic2_names) / sizeof(intrinsic2_names[0]);
333333

334+
static const char *format_value_names[] = {
335+
"FVC_NONE", "FVC_STR", "FVC_REPR", "FVC_ASCII",
336+
};
337+
static const size_t format_value_names_len = sizeof(format_value_names) / sizeof(format_value_names[0]);
338+
334339
PycBuffer source(code->code()->value(), code->code()->length());
335340

336341
int opcode, operand;
@@ -530,6 +535,18 @@ void bc_disasm(std::ostream& pyc_output, PycRef<PycCode> code, PycModule* mod,
530535
else
531536
formatted_print(pyc_output, "%d (UNKNOWN)", operand);
532537
break;
538+
case Pyc::FORMAT_VALUE_A:
539+
{
540+
auto conv = static_cast<size_t>(operand & 0x03);
541+
const char *flag = (operand & 0x04) ? " | FVS_HAVE_SPEC" : "";
542+
if (conv < format_value_names_len) {
543+
formatted_print(pyc_output, "%d (%s%s)", operand,
544+
format_value_names[conv], flag);
545+
} else {
546+
formatted_print(pyc_output, "%d (UNKNOWN)", operand);
547+
}
548+
}
549+
break;
533550
default:
534551
formatted_print(pyc_output, "%d", operand);
535552
break;

bytecode_ops.inl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ OPCODE_A(BUILD_MAP_UNPACK_WITH_CALL) // Python 3.5 A=(count
204204
OPCODE_A(BUILD_TUPLE_UNPACK) // Python 3.5 - 3.8 A=count
205205
OPCODE_A(BUILD_SET_UNPACK) // Python 3.5 - 3.8 A=count
206206
OPCODE_A(SETUP_ASYNC_WITH) // Python 3.5 - 3.10 rel jmp +A
207-
OPCODE_A(FORMAT_VALUE) // Python 3.6 -> A=conversion_type
207+
OPCODE_A(FORMAT_VALUE) // Python 3.6 -> A=(conversion_type&0x3)+(flags)
208208
OPCODE_A(BUILD_CONST_KEY_MAP) // Python 3.6 -> A=count
209209
OPCODE_A(BUILD_STRING) // Python 3.6 -> A=count
210210
OPCODE_A(BUILD_TUPLE_UNPACK_WITH_CALL) // Python 3.6 - 3.8 A=count

tests/compiled/f-string.3.7.pyc

-5 Bytes
Binary file not shown.

tests/input/f-string.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@
2828
print(f'''some {{braces}} {"inner literal: {braces} {{double braces}}"}''')
2929
print(f'''f-string dict {some_dict[2]} and {{function call in expression}}: {max([1,20,3])}''')
3030
print(f'{(lambda x: x*2)(3)}')
31+
print(f'{var3!s:4.5}')
3132
msg = (
3233
f'a {var1}'
3334
f'cool'
3435
f'multiline {var2}\n'
3536
f'f-string {var3}'
3637
)
37-
print(f'{now:%Y-%m-%d %H:%M}')
38+
print(f'{now:%Y-%m-%d %H:%M}')

tests/tokenized/f-string.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,6 @@ print ( f'{var3 * x} {var3:.2f} {var3:.5f} {x:02} {x * x:3} {x * x * x:4} {s1:>1
2727
print ( f'some {{braces}} {\'inner literal: {braces} {{double braces}}\'}' ) <EOL>
2828
print ( f'f-string dict {some_dict[2]} and {{function call in expression}}: {max([\n 1,\n 20,\n 3])}' ) <EOL>
2929
print ( f'{(lambda x: x * 2)(3)}' ) <EOL>
30+
print ( f'{var3!s:4.5}' ) <EOL>
3031
msg = f'a {var1}coolmultiline {var2}\nf-string {var3}' <EOL>
3132
print ( f'{now:%Y-%m-%d %H:%M}' ) <EOL>

0 commit comments

Comments
 (0)