rustpython_vm/builtins/
frame.rs

1/*! The python `frame` type.
2
3*/
4
5use 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        // TODO
39    }
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        // TODO: actually store f_back inside Frame struct
117
118        // get the frame in the frame stack that appears before this one.
119        // won't work if  this frame isn't in the frame stack, hence the todo above
120        vm.frames
121            .borrow()
122            .iter()
123            .rev()
124            .skip_while(|p| !p.is(self.as_object()))
125            .nth(1)
126            .cloned()
127    }
128}
Morty Proxy This is a proxified and sanitized view of the page, visit original site.