Skip to content

Commit 4c28d84

Browse files
authored
Merge pull request #4037 from youknowone/dis-fmt
enhance dis output to print line numbers
2 parents 662910e + 421de1a commit 4c28d84

8 files changed

Lines changed: 197 additions & 141 deletions

Lib/test/test_exceptions.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2633,8 +2633,6 @@ def f():
26332633
f.__code__ = f.__code__.replace(co_linetable=b'\x04\x80\xff\x80')
26342634
self.lineno_after_raise(f, None)
26352635

2636-
# TODO: RUSTPYTHON
2637-
@unittest.expectedFailure
26382636
def test_lineno_after_raise_in_with_exit(self):
26392637
class ExitFails:
26402638
def __enter__(self):

bytecode/src/lib.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -695,17 +695,39 @@ impl<C: Constant> CodeObject<C> {
695695
level: usize,
696696
) -> fmt::Result {
697697
let label_targets = self.label_targets();
698-
698+
let line_digits = (3).max(self.locations.last().unwrap().row.to_string().len());
699+
let offset_digits = (4).max(self.instructions.len().to_string().len());
700+
let mut last_line = u32::MAX;
699701
for (offset, instruction) in self.instructions.iter().enumerate() {
702+
// optional line number
703+
let line = self.locations[offset].row;
704+
if line != last_line {
705+
if last_line != u32::MAX {
706+
writeln!(f)?;
707+
}
708+
last_line = line;
709+
write!(f, "{line:line_digits$}")?;
710+
} else {
711+
for _ in 0..line_digits {
712+
write!(f, " ")?;
713+
}
714+
}
715+
write!(f, " ")?;
716+
717+
// level indent
718+
for _ in 0..level {
719+
write!(f, " ")?;
720+
}
721+
722+
// arrow and offset
700723
let arrow = if label_targets.contains(&Label(offset as u32)) {
701724
">>"
702725
} else {
703726
" "
704727
};
705-
for _ in 0..level {
706-
write!(f, " ")?;
707-
}
708-
write!(f, "{} {:5} ", arrow, offset)?;
728+
write!(f, "{arrow} {offset:offset_digits$} ")?;
729+
730+
// instruction
709731
instruction.fmt_dis(
710732
f,
711733
&self.constants,

compiler/src/compile.rs

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,54 +1393,69 @@ impl Compiler {
13931393
body: &[ast::Stmt],
13941394
is_async: bool,
13951395
) -> CompileResult<()> {
1396-
let end_blocks = items
1397-
.iter()
1398-
.map(|item| {
1399-
let end_block = self.new_block();
1400-
self.compile_expression(&item.context_expr)?;
1396+
let with_location = self.current_source_location;
14011397

1402-
if is_async {
1403-
self.emit(Instruction::BeforeAsyncWith);
1404-
self.emit(Instruction::GetAwaitable);
1405-
self.emit_constant(ConstantData::None);
1406-
self.emit(Instruction::YieldFrom);
1407-
self.emit(Instruction::SetupAsyncWith { end: end_block });
1408-
} else {
1409-
self.emit(Instruction::SetupWith { end: end_block });
1410-
}
1398+
let (item, items) = if let Some(parts) = items.split_first() {
1399+
parts
1400+
} else {
1401+
return Err(self.error(CompileErrorType::EmptyWithItems));
1402+
};
14111403

1412-
match &item.optional_vars {
1413-
Some(var) => {
1414-
self.compile_store(var)?;
1415-
}
1416-
None => {
1417-
self.emit(Instruction::Pop);
1418-
}
1404+
let final_block = {
1405+
let final_block = self.new_block();
1406+
self.compile_expression(&item.context_expr)?;
1407+
1408+
self.set_source_location(with_location);
1409+
if is_async {
1410+
self.emit(Instruction::BeforeAsyncWith);
1411+
self.emit(Instruction::GetAwaitable);
1412+
self.emit_constant(ConstantData::None);
1413+
self.emit(Instruction::YieldFrom);
1414+
self.emit(Instruction::SetupAsyncWith { end: final_block });
1415+
} else {
1416+
self.emit(Instruction::SetupWith { end: final_block });
1417+
}
1418+
1419+
match &item.optional_vars {
1420+
Some(var) => {
1421+
self.set_source_location(var.location);
1422+
self.compile_store(var)?;
1423+
}
1424+
None => {
1425+
self.emit(Instruction::Pop);
14191426
}
1420-
Ok(end_block)
1421-
})
1422-
.collect::<CompileResult<Vec<_>>>()?;
1427+
}
1428+
final_block
1429+
};
14231430

1424-
self.compile_statements(body)?;
1431+
if items.is_empty() {
1432+
if body.is_empty() {
1433+
return Err(self.error(CompileErrorType::EmptyWithBody));
1434+
}
1435+
self.compile_statements(body)?;
1436+
} else {
1437+
self.set_source_location(with_location);
1438+
self.compile_with(items, body, is_async)?;
1439+
}
14251440

14261441
// sort of "stack up" the layers of with blocks:
14271442
// with a, b: body -> start_with(a) start_with(b) body() end_with(b) end_with(a)
1428-
for end_block in end_blocks.into_iter().rev() {
1429-
self.emit(Instruction::PopBlock);
1430-
self.emit(Instruction::EnterFinally);
1443+
self.set_source_location(with_location);
1444+
self.emit(Instruction::PopBlock);
14311445

1432-
self.switch_to_block(end_block);
1433-
self.emit(Instruction::WithCleanupStart);
1446+
self.emit(Instruction::EnterFinally);
14341447

1435-
if is_async {
1436-
self.emit(Instruction::GetAwaitable);
1437-
self.emit_constant(ConstantData::None);
1438-
self.emit(Instruction::YieldFrom);
1439-
}
1448+
self.switch_to_block(final_block);
1449+
self.emit(Instruction::WithCleanupStart);
14401450

1441-
self.emit(Instruction::WithCleanupFinish);
1451+
if is_async {
1452+
self.emit(Instruction::GetAwaitable);
1453+
self.emit_constant(ConstantData::None);
1454+
self.emit(Instruction::YieldFrom);
14421455
}
14431456

1457+
self.emit(Instruction::WithCleanupFinish);
1458+
14441459
Ok(())
14451460
}
14461461

compiler/src/error.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ pub enum CompileErrorType {
3535
InvalidFutureFeature(String),
3636
FunctionImportStar,
3737
TooManyStarUnpack,
38+
EmptyWithItems,
39+
EmptyWithBody,
3840
}
3941

4042
impl fmt::Display for CompileErrorType {
@@ -70,6 +72,12 @@ impl fmt::Display for CompileErrorType {
7072
CompileErrorType::TooManyStarUnpack => {
7173
write!(f, "too many expressions in star-unpacking assignment")
7274
}
75+
CompileErrorType::EmptyWithItems => {
76+
write!(f, "empty items on With")
77+
}
78+
CompileErrorType::EmptyWithBody => {
79+
write!(f, "empty body on With")
80+
}
7381
}
7482
}
7583
}

compiler/src/snapshots/rustpython_compiler_core__compile__tests__if_ands.snap

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
source: compiler/src/compile.rs
33
expression: "compile_exec(\"\\\nif True and False and False:\n pass\n\")"
44
---
5-
0 LoadConst (True)
6-
1 JumpIfFalse (6)
7-
2 LoadConst (False)
8-
3 JumpIfFalse (6)
9-
4 LoadConst (False)
10-
5 JumpIfFalse (6)
11-
>> 6 LoadConst (None)
12-
7 ReturnValue
5+
1 0 LoadConst (True)
6+
1 JumpIfFalse (6)
7+
2 LoadConst (False)
8+
3 JumpIfFalse (6)
9+
4 LoadConst (False)
10+
5 JumpIfFalse (6)
11+
12+
2 >> 6 LoadConst (None)
13+
7 ReturnValue
1314

compiler/src/snapshots/rustpython_compiler_core__compile__tests__if_mixed.snap

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22
source: compiler/src/compile.rs
33
expression: "compile_exec(\"\\\nif (True and False) or (False and True):\n pass\n\")"
44
---
5-
0 LoadConst (True)
6-
1 JumpIfFalse (4)
7-
2 LoadConst (False)
8-
3 JumpIfTrue (8)
9-
>> 4 LoadConst (False)
10-
5 JumpIfFalse (8)
11-
6 LoadConst (True)
12-
7 JumpIfFalse (8)
13-
>> 8 LoadConst (None)
14-
9 ReturnValue
5+
1 0 LoadConst (True)
6+
1 JumpIfFalse (4)
7+
2 LoadConst (False)
8+
3 JumpIfTrue (8)
9+
>> 4 LoadConst (False)
10+
5 JumpIfFalse (8)
11+
6 LoadConst (True)
12+
7 JumpIfFalse (8)
13+
14+
2 >> 8 LoadConst (None)
15+
9 ReturnValue
1516

compiler/src/snapshots/rustpython_compiler_core__compile__tests__if_ors.snap

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
source: compiler/src/compile.rs
33
expression: "compile_exec(\"\\\nif True or False or False:\n pass\n\")"
44
---
5-
0 LoadConst (True)
6-
1 JumpIfTrue (6)
7-
2 LoadConst (False)
8-
3 JumpIfTrue (6)
9-
4 LoadConst (False)
10-
5 JumpIfFalse (6)
11-
>> 6 LoadConst (None)
12-
7 ReturnValue
5+
1 0 LoadConst (True)
6+
1 JumpIfTrue (6)
7+
2 LoadConst (False)
8+
3 JumpIfTrue (6)
9+
4 LoadConst (False)
10+
5 JumpIfFalse (6)
11+
12+
2 >> 6 LoadConst (None)
13+
7 ReturnValue
1314

0 commit comments

Comments
 (0)