Skip to content

Commit 66a8aee

Browse files
committed
set_f_lineno, set_f_lasti
1 parent a373bbd commit 66a8aee

2 files changed

Lines changed: 51 additions & 0 deletions

File tree

crates/vm/src/builtins/frame.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,46 @@ impl Frame {
7171
}
7272
}
7373

74+
#[pygetset(setter)]
75+
fn set_f_lineno(&self, value: PySetterValue, vm: &VirtualMachine) -> PyResult<()> {
76+
let target_line = match value {
77+
PySetterValue::Assign(val) => {
78+
let line_ref: PyIntRef = val
79+
.downcast()
80+
.map_err(|_| vm.new_value_error("lineno must be an integer".to_owned()))?;
81+
line_ref
82+
.try_to_primitive::<usize>(vm)
83+
.map_err(|_| vm.new_value_error("lineno must be an integer".to_owned()))?
84+
}
85+
PySetterValue::Delete => {
86+
return Err(vm.new_type_error("can't delete f_lineno attribute".to_owned()));
87+
}
88+
};
89+
90+
// Find the first instruction at the target line
91+
let locations = &self.code.locations;
92+
let mut target_idx = None;
93+
for (idx, (loc, _)) in locations.iter().enumerate() {
94+
if loc.line.get() == target_line {
95+
target_idx = Some(idx);
96+
break;
97+
}
98+
}
99+
100+
match target_idx {
101+
Some(idx) => {
102+
// Set lasti to point to the target instruction.
103+
// The run loop reads lasti then increments, so set to idx
104+
// so the next iteration executes instruction at idx.
105+
self.set_lasti(idx as u32);
106+
Ok(())
107+
}
108+
None => Err(vm.new_value_error(format!(
109+
"line {target_line} comes after the current code block"
110+
))),
111+
}
112+
}
113+
74114
#[pygetset]
75115
fn f_trace(&self) -> PyObjectRef {
76116
let boxed = self.trace.lock();

crates/vm/src/frame.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,17 @@ impl Frame {
258258
}
259259
}
260260

261+
pub fn set_lasti(&self, val: u32) {
262+
#[cfg(feature = "threading")]
263+
{
264+
self.lasti.store(val, atomic::Ordering::Relaxed);
265+
}
266+
#[cfg(not(feature = "threading"))]
267+
{
268+
self.lasti.set(val);
269+
}
270+
}
271+
261272
/// Sync locals dict back to fastlocals. Called before generator/coroutine resume
262273
/// to apply any modifications made via f_locals.
263274
pub fn locals_to_fast(&self, vm: &VirtualMachine) -> PyResult<()> {

0 commit comments

Comments
 (0)