rustpython_vm/builtins/
frame.rs1use super::{PyCode, PyDictRef, PyIntRef, PyStrRef};
6use crate::{
7 class::PyClassImpl,
8 frame::{Frame, FrameRef},
9 function::PySetterValue,
10 types::{Representable, Unconstructible},
11 AsObject, Context, Py, PyObjectRef, PyRef, PyResult, VirtualMachine,
12};
13use num_traits::Zero;
14
15pub fn init(context: &Context) {
16 Frame::extend_class(context, context.types.frame_type);
17}
18
19impl Unconstructible for Frame {}
20
21impl Representable for Frame {
22 #[inline]
23 fn repr(_zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
24 const REPR: &str = "<frame object at .. >";
25 Ok(vm.ctx.intern_str(REPR).to_owned())
26 }
27
28 #[cold]
29 fn repr_str(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
30 unreachable!("use repr instead")
31 }
32}
33
34#[pyclass(with(Unconstructible, Py))]
35impl Frame {
36 #[pymethod]
37 fn clear(&self) {
38 }
40
41 #[pygetset]
42 fn f_globals(&self) -> PyDictRef {
43 self.globals.clone()
44 }
45
46 #[pygetset]
47 fn f_locals(&self, vm: &VirtualMachine) -> PyResult {
48 self.locals(vm).map(Into::into)
49 }
50
51 #[pygetset]
52 pub fn f_code(&self) -> PyRef<PyCode> {
53 self.code.clone()
54 }
55
56 #[pygetset]
57 fn f_lasti(&self) -> u32 {
58 self.lasti()
59 }
60
61 #[pygetset]
62 pub fn f_lineno(&self) -> usize {
63 self.current_location().row.to_usize()
64 }
65
66 #[pygetset]
67 fn f_trace(&self) -> PyObjectRef {
68 let boxed = self.trace.lock();
69 boxed.clone()
70 }
71
72 #[pygetset(setter)]
73 fn set_f_trace(&self, value: PySetterValue, vm: &VirtualMachine) {
74 let mut storage = self.trace.lock();
75 *storage = value.unwrap_or_none(vm);
76 }
77
78 #[pymember(type = "bool")]
79 fn f_trace_lines(vm: &VirtualMachine, zelf: PyObjectRef) -> PyResult {
80 let zelf: FrameRef = zelf.downcast().unwrap_or_else(|_| unreachable!());
81
82 let boxed = zelf.trace_lines.lock();
83 Ok(vm.ctx.new_bool(*boxed).into())
84 }
85
86 #[pymember(type = "bool", setter)]
87 fn set_f_trace_lines(
88 vm: &VirtualMachine,
89 zelf: PyObjectRef,
90 value: PySetterValue,
91 ) -> PyResult<()> {
92 match value {
93 PySetterValue::Assign(value) => {
94 let zelf: FrameRef = zelf.downcast().unwrap_or_else(|_| unreachable!());
95
96 let value: PyIntRef = value.downcast().map_err(|_| {
97 vm.new_type_error("attribute value type must be bool".to_owned())
98 })?;
99
100 let mut trace_lines = zelf.trace_lines.lock();
101 *trace_lines = !value.as_bigint().is_zero();
102
103 Ok(())
104 }
105 PySetterValue::Delete => {
106 Err(vm.new_type_error("can't delete numeric/char attribute".to_owned()))
107 }
108 }
109 }
110}
111
112#[pyclass]
113impl Py<Frame> {
114 #[pygetset]
115 pub fn f_back(&self, vm: &VirtualMachine) -> Option<PyRef<Frame>> {
116 vm.frames
121 .borrow()
122 .iter()
123 .rev()
124 .skip_while(|p| !p.is(self.as_object()))
125 .nth(1)
126 .cloned()
127 }
128}