forked from Rust-related/RustPython
Merge pull request #4037 from youknowone/dis-fmt
enhance dis output to print line numbers
This commit is contained in:
2
Lib/test/test_exceptions.py
vendored
2
Lib/test/test_exceptions.py
vendored
@@ -2633,8 +2633,6 @@ class PEP626Tests(unittest.TestCase):
|
||||
f.__code__ = f.__code__.replace(co_linetable=b'\x04\x80\xff\x80')
|
||||
self.lineno_after_raise(f, None)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_lineno_after_raise_in_with_exit(self):
|
||||
class ExitFails:
|
||||
def __enter__(self):
|
||||
|
||||
@@ -695,17 +695,39 @@ impl<C: Constant> CodeObject<C> {
|
||||
level: usize,
|
||||
) -> fmt::Result {
|
||||
let label_targets = self.label_targets();
|
||||
|
||||
let line_digits = (3).max(self.locations.last().unwrap().row.to_string().len());
|
||||
let offset_digits = (4).max(self.instructions.len().to_string().len());
|
||||
let mut last_line = u32::MAX;
|
||||
for (offset, instruction) in self.instructions.iter().enumerate() {
|
||||
// optional line number
|
||||
let line = self.locations[offset].row;
|
||||
if line != last_line {
|
||||
if last_line != u32::MAX {
|
||||
writeln!(f)?;
|
||||
}
|
||||
last_line = line;
|
||||
write!(f, "{line:line_digits$}")?;
|
||||
} else {
|
||||
for _ in 0..line_digits {
|
||||
write!(f, " ")?;
|
||||
}
|
||||
}
|
||||
write!(f, " ")?;
|
||||
|
||||
// level indent
|
||||
for _ in 0..level {
|
||||
write!(f, " ")?;
|
||||
}
|
||||
|
||||
// arrow and offset
|
||||
let arrow = if label_targets.contains(&Label(offset as u32)) {
|
||||
">>"
|
||||
} else {
|
||||
" "
|
||||
};
|
||||
for _ in 0..level {
|
||||
write!(f, " ")?;
|
||||
}
|
||||
write!(f, "{} {:5} ", arrow, offset)?;
|
||||
write!(f, "{arrow} {offset:offset_digits$} ")?;
|
||||
|
||||
// instruction
|
||||
instruction.fmt_dis(
|
||||
f,
|
||||
&self.constants,
|
||||
|
||||
@@ -1393,54 +1393,69 @@ impl Compiler {
|
||||
body: &[ast::Stmt],
|
||||
is_async: bool,
|
||||
) -> CompileResult<()> {
|
||||
let end_blocks = items
|
||||
.iter()
|
||||
.map(|item| {
|
||||
let end_block = self.new_block();
|
||||
self.compile_expression(&item.context_expr)?;
|
||||
let with_location = self.current_source_location;
|
||||
|
||||
if is_async {
|
||||
self.emit(Instruction::BeforeAsyncWith);
|
||||
self.emit(Instruction::GetAwaitable);
|
||||
self.emit_constant(ConstantData::None);
|
||||
self.emit(Instruction::YieldFrom);
|
||||
self.emit(Instruction::SetupAsyncWith { end: end_block });
|
||||
} else {
|
||||
self.emit(Instruction::SetupWith { end: end_block });
|
||||
}
|
||||
let (item, items) = if let Some(parts) = items.split_first() {
|
||||
parts
|
||||
} else {
|
||||
return Err(self.error(CompileErrorType::EmptyWithItems));
|
||||
};
|
||||
|
||||
match &item.optional_vars {
|
||||
Some(var) => {
|
||||
self.compile_store(var)?;
|
||||
}
|
||||
None => {
|
||||
self.emit(Instruction::Pop);
|
||||
}
|
||||
}
|
||||
Ok(end_block)
|
||||
})
|
||||
.collect::<CompileResult<Vec<_>>>()?;
|
||||
|
||||
self.compile_statements(body)?;
|
||||
|
||||
// sort of "stack up" the layers of with blocks:
|
||||
// with a, b: body -> start_with(a) start_with(b) body() end_with(b) end_with(a)
|
||||
for end_block in end_blocks.into_iter().rev() {
|
||||
self.emit(Instruction::PopBlock);
|
||||
self.emit(Instruction::EnterFinally);
|
||||
|
||||
self.switch_to_block(end_block);
|
||||
self.emit(Instruction::WithCleanupStart);
|
||||
let final_block = {
|
||||
let final_block = self.new_block();
|
||||
self.compile_expression(&item.context_expr)?;
|
||||
|
||||
self.set_source_location(with_location);
|
||||
if is_async {
|
||||
self.emit(Instruction::BeforeAsyncWith);
|
||||
self.emit(Instruction::GetAwaitable);
|
||||
self.emit_constant(ConstantData::None);
|
||||
self.emit(Instruction::YieldFrom);
|
||||
self.emit(Instruction::SetupAsyncWith { end: final_block });
|
||||
} else {
|
||||
self.emit(Instruction::SetupWith { end: final_block });
|
||||
}
|
||||
|
||||
self.emit(Instruction::WithCleanupFinish);
|
||||
match &item.optional_vars {
|
||||
Some(var) => {
|
||||
self.set_source_location(var.location);
|
||||
self.compile_store(var)?;
|
||||
}
|
||||
None => {
|
||||
self.emit(Instruction::Pop);
|
||||
}
|
||||
}
|
||||
final_block
|
||||
};
|
||||
|
||||
if items.is_empty() {
|
||||
if body.is_empty() {
|
||||
return Err(self.error(CompileErrorType::EmptyWithBody));
|
||||
}
|
||||
self.compile_statements(body)?;
|
||||
} else {
|
||||
self.set_source_location(with_location);
|
||||
self.compile_with(items, body, is_async)?;
|
||||
}
|
||||
|
||||
// sort of "stack up" the layers of with blocks:
|
||||
// with a, b: body -> start_with(a) start_with(b) body() end_with(b) end_with(a)
|
||||
self.set_source_location(with_location);
|
||||
self.emit(Instruction::PopBlock);
|
||||
|
||||
self.emit(Instruction::EnterFinally);
|
||||
|
||||
self.switch_to_block(final_block);
|
||||
self.emit(Instruction::WithCleanupStart);
|
||||
|
||||
if is_async {
|
||||
self.emit(Instruction::GetAwaitable);
|
||||
self.emit_constant(ConstantData::None);
|
||||
self.emit(Instruction::YieldFrom);
|
||||
}
|
||||
|
||||
self.emit(Instruction::WithCleanupFinish);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ pub enum CompileErrorType {
|
||||
InvalidFutureFeature(String),
|
||||
FunctionImportStar,
|
||||
TooManyStarUnpack,
|
||||
EmptyWithItems,
|
||||
EmptyWithBody,
|
||||
}
|
||||
|
||||
impl fmt::Display for CompileErrorType {
|
||||
@@ -70,6 +72,12 @@ impl fmt::Display for CompileErrorType {
|
||||
CompileErrorType::TooManyStarUnpack => {
|
||||
write!(f, "too many expressions in star-unpacking assignment")
|
||||
}
|
||||
CompileErrorType::EmptyWithItems => {
|
||||
write!(f, "empty items on With")
|
||||
}
|
||||
CompileErrorType::EmptyWithBody => {
|
||||
write!(f, "empty body on With")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
source: compiler/src/compile.rs
|
||||
expression: "compile_exec(\"\\\nif True and False and False:\n pass\n\")"
|
||||
---
|
||||
0 LoadConst (True)
|
||||
1 JumpIfFalse (6)
|
||||
2 LoadConst (False)
|
||||
3 JumpIfFalse (6)
|
||||
4 LoadConst (False)
|
||||
5 JumpIfFalse (6)
|
||||
>> 6 LoadConst (None)
|
||||
7 ReturnValue
|
||||
1 0 LoadConst (True)
|
||||
1 JumpIfFalse (6)
|
||||
2 LoadConst (False)
|
||||
3 JumpIfFalse (6)
|
||||
4 LoadConst (False)
|
||||
5 JumpIfFalse (6)
|
||||
|
||||
2 >> 6 LoadConst (None)
|
||||
7 ReturnValue
|
||||
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
source: compiler/src/compile.rs
|
||||
expression: "compile_exec(\"\\\nif (True and False) or (False and True):\n pass\n\")"
|
||||
---
|
||||
0 LoadConst (True)
|
||||
1 JumpIfFalse (4)
|
||||
2 LoadConst (False)
|
||||
3 JumpIfTrue (8)
|
||||
>> 4 LoadConst (False)
|
||||
5 JumpIfFalse (8)
|
||||
6 LoadConst (True)
|
||||
7 JumpIfFalse (8)
|
||||
>> 8 LoadConst (None)
|
||||
9 ReturnValue
|
||||
1 0 LoadConst (True)
|
||||
1 JumpIfFalse (4)
|
||||
2 LoadConst (False)
|
||||
3 JumpIfTrue (8)
|
||||
>> 4 LoadConst (False)
|
||||
5 JumpIfFalse (8)
|
||||
6 LoadConst (True)
|
||||
7 JumpIfFalse (8)
|
||||
|
||||
2 >> 8 LoadConst (None)
|
||||
9 ReturnValue
|
||||
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
source: compiler/src/compile.rs
|
||||
expression: "compile_exec(\"\\\nif True or False or False:\n pass\n\")"
|
||||
---
|
||||
0 LoadConst (True)
|
||||
1 JumpIfTrue (6)
|
||||
2 LoadConst (False)
|
||||
3 JumpIfTrue (6)
|
||||
4 LoadConst (False)
|
||||
5 JumpIfFalse (6)
|
||||
>> 6 LoadConst (None)
|
||||
7 ReturnValue
|
||||
1 0 LoadConst (True)
|
||||
1 JumpIfTrue (6)
|
||||
2 LoadConst (False)
|
||||
3 JumpIfTrue (6)
|
||||
4 LoadConst (False)
|
||||
5 JumpIfFalse (6)
|
||||
|
||||
2 >> 6 LoadConst (None)
|
||||
7 ReturnValue
|
||||
|
||||
|
||||
@@ -1,77 +1,87 @@
|
||||
---
|
||||
source: compiler/src/compile.rs
|
||||
expression: "compile_exec(\"\\\nfor stop_exc in (StopIteration('spam'), StopAsyncIteration('ham')):\n with self.subTest(type=type(stop_exc)):\n try:\n async with woohoo():\n raise stop_exc\n except Exception as ex:\n self.assertIs(ex, stop_exc)\n else:\n self.fail(f'{stop_exc} was suppressed')\n\")"
|
||||
|
||||
---
|
||||
0 SetupLoop (69)
|
||||
1 LoadNameAny (0, StopIteration)
|
||||
2 LoadConst ("spam")
|
||||
3 CallFunctionPositional (1)
|
||||
4 LoadNameAny (1, StopAsyncIteration)
|
||||
5 LoadConst ("ham")
|
||||
6 CallFunctionPositional (1)
|
||||
7 BuildTuple (2, false)
|
||||
8 GetIter
|
||||
>> 9 ForIter (68)
|
||||
10 StoreLocal (2, stop_exc)
|
||||
11 LoadNameAny (3, self)
|
||||
12 LoadMethod (subTest)
|
||||
13 LoadNameAny (5, type)
|
||||
14 LoadNameAny (2, stop_exc)
|
||||
15 CallFunctionPositional (1)
|
||||
16 LoadConst (("type"))
|
||||
17 CallMethodKeyword (1)
|
||||
18 SetupWith (65)
|
||||
19 Pop
|
||||
20 SetupExcept (40)
|
||||
21 LoadNameAny (6, woohoo)
|
||||
22 CallFunctionPositional (0)
|
||||
23 BeforeAsyncWith
|
||||
24 GetAwaitable
|
||||
25 LoadConst (None)
|
||||
26 YieldFrom
|
||||
27 SetupAsyncWith (33)
|
||||
28 Pop
|
||||
29 LoadNameAny (2, stop_exc)
|
||||
30 Raise (Raise)
|
||||
31 PopBlock
|
||||
32 EnterFinally
|
||||
>> 33 WithCleanupStart
|
||||
34 GetAwaitable
|
||||
35 LoadConst (None)
|
||||
36 YieldFrom
|
||||
37 WithCleanupFinish
|
||||
38 PopBlock
|
||||
39 Jump (54)
|
||||
>> 40 Duplicate
|
||||
41 LoadNameAny (7, Exception)
|
||||
42 TestOperation (ExceptionMatch)
|
||||
43 JumpIfFalse (53)
|
||||
44 StoreLocal (8, ex)
|
||||
45 LoadNameAny (3, self)
|
||||
46 LoadMethod (assertIs)
|
||||
47 LoadNameAny (8, ex)
|
||||
48 LoadNameAny (2, stop_exc)
|
||||
49 CallMethodPositional (2)
|
||||
50 Pop
|
||||
51 PopException
|
||||
52 Jump (63)
|
||||
>> 53 Raise (Reraise)
|
||||
>> 54 LoadNameAny (3, self)
|
||||
55 LoadMethod (fail)
|
||||
56 LoadConst ("")
|
||||
57 LoadNameAny (2, stop_exc)
|
||||
58 FormatValue (None)
|
||||
59 LoadConst (" was suppressed")
|
||||
60 BuildString (2)
|
||||
61 CallMethodPositional (1)
|
||||
62 Pop
|
||||
>> 63 PopBlock
|
||||
64 EnterFinally
|
||||
>> 65 WithCleanupStart
|
||||
66 WithCleanupFinish
|
||||
67 Jump (9)
|
||||
>> 68 PopBlock
|
||||
>> 69 LoadConst (None)
|
||||
70 ReturnValue
|
||||
1 0 SetupLoop (69)
|
||||
1 LoadNameAny (0, StopIteration)
|
||||
2 LoadConst ("spam")
|
||||
3 CallFunctionPositional (1)
|
||||
4 LoadNameAny (1, StopAsyncIteration)
|
||||
5 LoadConst ("ham")
|
||||
6 CallFunctionPositional (1)
|
||||
7 BuildTuple (2, false)
|
||||
8 GetIter
|
||||
>> 9 ForIter (68)
|
||||
10 StoreLocal (2, stop_exc)
|
||||
|
||||
2 11 LoadNameAny (3, self)
|
||||
12 LoadMethod (subTest)
|
||||
13 LoadNameAny (5, type)
|
||||
14 LoadNameAny (2, stop_exc)
|
||||
15 CallFunctionPositional (1)
|
||||
16 LoadConst (("type"))
|
||||
17 CallMethodKeyword (1)
|
||||
18 SetupWith (65)
|
||||
19 Pop
|
||||
|
||||
3 20 SetupExcept (40)
|
||||
|
||||
4 21 LoadNameAny (6, woohoo)
|
||||
22 CallFunctionPositional (0)
|
||||
23 BeforeAsyncWith
|
||||
24 GetAwaitable
|
||||
25 LoadConst (None)
|
||||
26 YieldFrom
|
||||
27 SetupAsyncWith (33)
|
||||
28 Pop
|
||||
|
||||
5 29 LoadNameAny (2, stop_exc)
|
||||
30 Raise (Raise)
|
||||
|
||||
4 31 PopBlock
|
||||
32 EnterFinally
|
||||
>> 33 WithCleanupStart
|
||||
34 GetAwaitable
|
||||
35 LoadConst (None)
|
||||
36 YieldFrom
|
||||
37 WithCleanupFinish
|
||||
38 PopBlock
|
||||
39 Jump (54)
|
||||
>> 40 Duplicate
|
||||
|
||||
6 41 LoadNameAny (7, Exception)
|
||||
42 TestOperation (ExceptionMatch)
|
||||
43 JumpIfFalse (53)
|
||||
44 StoreLocal (8, ex)
|
||||
|
||||
7 45 LoadNameAny (3, self)
|
||||
46 LoadMethod (assertIs)
|
||||
47 LoadNameAny (8, ex)
|
||||
48 LoadNameAny (2, stop_exc)
|
||||
49 CallMethodPositional (2)
|
||||
50 Pop
|
||||
51 PopException
|
||||
52 Jump (63)
|
||||
>> 53 Raise (Reraise)
|
||||
|
||||
9 >> 54 LoadNameAny (3, self)
|
||||
55 LoadMethod (fail)
|
||||
56 LoadConst ("")
|
||||
|
||||
1 57 LoadNameAny (2, stop_exc)
|
||||
58 FormatValue (None)
|
||||
|
||||
9 59 LoadConst (" was suppressed")
|
||||
60 BuildString (2)
|
||||
61 CallMethodPositional (1)
|
||||
62 Pop
|
||||
|
||||
2 >> 63 PopBlock
|
||||
64 EnterFinally
|
||||
>> 65 WithCleanupStart
|
||||
66 WithCleanupFinish
|
||||
67 Jump (9)
|
||||
>> 68 PopBlock
|
||||
>> 69 LoadConst (None)
|
||||
70 ReturnValue
|
||||
|
||||
|
||||
Reference in New Issue
Block a user