Skip to content

Commit 79b4f62

Browse files
Merge pull request #642 from RustPython/joey/function-to-any
Convert function, method, builtin_*, frame, and generator to Any payload
2 parents f57d2e2 + 6eea407 commit 79b4f62

File tree

8 files changed

+149
-78
lines changed

8 files changed

+149
-78
lines changed

vm/src/frame.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::builtins;
1111
use crate::bytecode;
1212
use crate::import::{import, import_module};
1313
use crate::obj::objbool;
14+
use crate::obj::objbuiltinfunc::PyBuiltinFunction;
1415
use crate::obj::objcode;
1516
use crate::obj::objdict;
1617
use crate::obj::objdict::PyDict;
@@ -20,8 +21,8 @@ use crate::obj::objlist;
2021
use crate::obj::objstr;
2122
use crate::obj::objtype;
2223
use crate::pyobject::{
23-
DictProtocol, IdProtocol, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult,
24-
TryFromObject, TypeProtocol,
24+
DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2,
25+
PyObjectRef, PyResult, TryFromObject, TypeProtocol,
2526
};
2627
use crate::vm::VirtualMachine;
2728

@@ -75,6 +76,12 @@ pub struct Frame {
7576
pub lasti: RefCell<usize>, // index of last instruction ran
7677
}
7778

79+
impl PyObjectPayload2 for Frame {
80+
fn required_type(ctx: &PyContext) -> PyObjectRef {
81+
ctx.frame_type()
82+
}
83+
}
84+
7885
// Running a frame can result in one of the below:
7986
pub enum ExecutionResult {
8087
Return(PyObjectRef),
@@ -592,8 +599,10 @@ impl Frame {
592599
}
593600
bytecode::Instruction::LoadBuildClass => {
594601
let rustfunc = PyObject::new(
595-
PyObjectPayload::RustFunction {
596-
function: Box::new(builtins::builtin_build_class_),
602+
PyObjectPayload::AnyRustValue {
603+
value: Box::new(PyBuiltinFunction::new(Box::new(
604+
builtins::builtin_build_class_,
605+
))),
597606
},
598607
vm.ctx.type_type(),
599608
);

vm/src/obj/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! This package contains the python basic/builtin types
22
33
pub mod objbool;
4+
pub mod objbuiltinfunc;
45
pub mod objbytearray;
56
pub mod objbytes;
67
pub mod objcode;

vm/src/obj/objbuiltinfunc.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use std::fmt;
2+
3+
use crate::pyobject::{PyContext, PyNativeFunc, PyObjectPayload2, PyObjectRef};
4+
5+
pub struct PyBuiltinFunction {
6+
// TODO: shouldn't be public
7+
pub value: PyNativeFunc,
8+
}
9+
10+
impl PyObjectPayload2 for PyBuiltinFunction {
11+
fn required_type(ctx: &PyContext) -> PyObjectRef {
12+
ctx.builtin_function_or_method_type()
13+
}
14+
}
15+
16+
impl fmt::Debug for PyBuiltinFunction {
17+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18+
write!(f, "builtin function")
19+
}
20+
}
21+
22+
impl PyBuiltinFunction {
23+
pub fn new(value: PyNativeFunc) -> Self {
24+
Self { value }
25+
}
26+
}

vm/src/obj/objframe.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
*/
44

55
use crate::frame::Frame;
6-
use crate::pyobject::{
7-
PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
8-
};
6+
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
97
use crate::vm::VirtualMachine;
108

119
pub fn init(context: &PyContext) {
@@ -39,9 +37,5 @@ fn frame_fcode(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
3937
}
4038

4139
pub fn get_value(obj: &PyObjectRef) -> &Frame {
42-
if let PyObjectPayload::Frame { frame } = &obj.payload {
43-
frame
44-
} else {
45-
panic!("Inner error getting int {:?}", obj);
46-
}
40+
&obj.payload::<Frame>().unwrap()
4741
}

vm/src/obj/objfunction.rs

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,53 @@
1+
use crate::frame::ScopeRef;
12
use crate::pyobject::{
2-
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectPayload, PyResult, TypeProtocol,
3+
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectPayload2, PyObjectRef, PyResult,
4+
TypeProtocol,
35
};
46
use crate::vm::VirtualMachine;
57

8+
#[derive(Debug)]
9+
pub struct PyFunction {
10+
// TODO: these shouldn't be public
11+
pub code: PyObjectRef,
12+
pub scope: ScopeRef,
13+
pub defaults: PyObjectRef,
14+
}
15+
16+
impl PyFunction {
17+
pub fn new(code: PyObjectRef, scope: ScopeRef, defaults: PyObjectRef) -> Self {
18+
PyFunction {
19+
code,
20+
scope,
21+
defaults,
22+
}
23+
}
24+
}
25+
26+
impl PyObjectPayload2 for PyFunction {
27+
fn required_type(ctx: &PyContext) -> PyObjectRef {
28+
ctx.function_type()
29+
}
30+
}
31+
32+
#[derive(Debug)]
33+
pub struct PyMethod {
34+
// TODO: these shouldn't be public
35+
pub object: PyObjectRef,
36+
pub function: PyObjectRef,
37+
}
38+
39+
impl PyMethod {
40+
pub fn new(object: PyObjectRef, function: PyObjectRef) -> Self {
41+
PyMethod { object, function }
42+
}
43+
}
44+
45+
impl PyObjectPayload2 for PyMethod {
46+
fn required_type(ctx: &PyContext) -> PyObjectRef {
47+
ctx.bound_method_type()
48+
}
49+
}
50+
651
pub fn init(context: &PyContext) {
752
let function_type = &context.function_type;
853
context.set_attr(&function_type, "__get__", context.new_rustfunc(bind_method));
@@ -79,9 +124,9 @@ fn bind_method(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
79124
}
80125

81126
fn function_code(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
82-
match args.args[0].payload {
83-
PyObjectPayload::Function { ref code, .. } => Ok(code.clone()),
84-
_ => Err(vm.new_type_error("no code".to_string())),
127+
match args.args[0].payload() {
128+
Some(PyFunction { ref code, .. }) => Ok(code.clone()),
129+
None => Err(vm.new_type_error("no code".to_string())),
85130
}
86131
}
87132

vm/src/obj/objgenerator.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,24 @@
22
* The mythical generator.
33
*/
44

5-
use crate::frame::ExecutionResult;
5+
use crate::frame::{ExecutionResult, Frame};
66
use crate::pyobject::{
7-
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
7+
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult,
8+
TypeProtocol,
89
};
910
use crate::vm::VirtualMachine;
1011

12+
#[derive(Debug)]
13+
pub struct PyGenerator {
14+
frame: PyObjectRef,
15+
}
16+
17+
impl PyObjectPayload2 for PyGenerator {
18+
fn required_type(ctx: &PyContext) -> PyObjectRef {
19+
ctx.generator_type()
20+
}
21+
}
22+
1123
pub fn init(context: &PyContext) {
1224
let generator_type = &context.generator_type;
1325
context.set_attr(
@@ -29,7 +41,9 @@ pub fn init(context: &PyContext) {
2941

3042
pub fn new_generator(vm: &mut VirtualMachine, frame: PyObjectRef) -> PyResult {
3143
Ok(PyObject::new(
32-
PyObjectPayload::Generator { frame },
44+
PyObjectPayload::AnyRustValue {
45+
value: Box::new(PyGenerator { frame }),
46+
},
3347
vm.ctx.generator_type.clone(),
3448
))
3549
}
@@ -55,8 +69,8 @@ fn generator_send(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
5569
}
5670

5771
fn send(vm: &mut VirtualMachine, gen: &PyObjectRef, value: &PyObjectRef) -> PyResult {
58-
if let PyObjectPayload::Generator { ref frame } = gen.payload {
59-
if let PyObjectPayload::Frame { ref frame } = frame.payload {
72+
if let Some(PyGenerator { ref frame }) = gen.payload() {
73+
if let Some(frame) = frame.payload::<Frame>() {
6074
frame.push_value(value.clone());
6175
} else {
6276
panic!("Generator frame isn't a frame.");

vm/src/pyobject.rs

Lines changed: 11 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::bytecode;
1414
use crate::exceptions;
1515
use crate::frame::{Frame, Scope, ScopeRef};
1616
use crate::obj::objbool;
17+
use crate::obj::objbuiltinfunc::PyBuiltinFunction;
1718
use crate::obj::objbytearray;
1819
use crate::obj::objbytes;
1920
use crate::obj::objcode;
@@ -24,7 +25,7 @@ use crate::obj::objenumerate;
2425
use crate::obj::objfilter;
2526
use crate::obj::objfloat::{self, PyFloat};
2627
use crate::obj::objframe;
27-
use crate::obj::objfunction;
28+
use crate::obj::objfunction::{self, PyFunction, PyMethod};
2829
use crate::obj::objgenerator;
2930
use crate::obj::objint::{self, PyInt};
3031
use crate::obj::objiter;
@@ -615,17 +616,17 @@ impl PyContext {
615616
F: IntoPyNativeFunc<T, R>,
616617
{
617618
PyObject::new(
618-
PyObjectPayload::RustFunction {
619-
function: f.into_func(),
619+
PyObjectPayload::AnyRustValue {
620+
value: Box::new(PyBuiltinFunction::new(f.into_func())),
620621
},
621622
self.builtin_function_or_method_type(),
622623
)
623624
}
624625

625626
pub fn new_frame(&self, code: PyObjectRef, scope: ScopeRef) -> PyObjectRef {
626627
PyObject::new(
627-
PyObjectPayload::Frame {
628-
frame: Frame::new(code, scope),
628+
PyObjectPayload::AnyRustValue {
629+
value: Box::new(Frame::new(code, scope)),
629630
},
630631
self.frame_type(),
631632
)
@@ -657,18 +658,18 @@ impl PyContext {
657658
defaults: PyObjectRef,
658659
) -> PyObjectRef {
659660
PyObject::new(
660-
PyObjectPayload::Function {
661-
code: code_obj,
662-
scope,
663-
defaults,
661+
PyObjectPayload::AnyRustValue {
662+
value: Box::new(PyFunction::new(code_obj, scope, defaults)),
664663
},
665664
self.function_type(),
666665
)
667666
}
668667

669668
pub fn new_bound_method(&self, function: PyObjectRef, object: PyObjectRef) -> PyObjectRef {
670669
PyObject::new(
671-
PyObjectPayload::BoundMethod { function, object },
670+
PyObjectPayload::AnyRustValue {
671+
value: Box::new(PyMethod::new(object, function)),
672+
},
672673
self.bound_method_type(),
673674
)
674675
}
@@ -1522,27 +1523,9 @@ pub enum PyObjectPayload {
15221523
MemoryView {
15231524
obj: PyObjectRef,
15241525
},
1525-
Frame {
1526-
frame: Frame,
1527-
},
1528-
Function {
1529-
code: PyObjectRef,
1530-
scope: ScopeRef,
1531-
defaults: PyObjectRef,
1532-
},
1533-
Generator {
1534-
frame: PyObjectRef,
1535-
},
1536-
BoundMethod {
1537-
function: PyObjectRef,
1538-
object: PyObjectRef,
1539-
},
15401526
WeakRef {
15411527
referent: PyObjectWeakRef,
15421528
},
1543-
RustFunction {
1544-
function: PyNativeFunc,
1545-
},
15461529
AnyRustValue {
15471530
value: Box<dyn std::any::Any>,
15481531
},
@@ -1563,14 +1546,6 @@ impl fmt::Debug for PyObjectPayload {
15631546
PyObjectPayload::WeakRef { .. } => write!(f, "weakref"),
15641547
PyObjectPayload::Iterator { .. } => write!(f, "iterator"),
15651548
PyObjectPayload::Slice { .. } => write!(f, "slice"),
1566-
PyObjectPayload::Function { .. } => write!(f, "function"),
1567-
PyObjectPayload::Generator { .. } => write!(f, "generator"),
1568-
PyObjectPayload::BoundMethod {
1569-
ref function,
1570-
ref object,
1571-
} => write!(f, "bound-method: {:?} of {:?}", function, object),
1572-
PyObjectPayload::RustFunction { .. } => write!(f, "rust function"),
1573-
PyObjectPayload::Frame { .. } => write!(f, "frame"),
15741549
PyObjectPayload::AnyRustValue { value } => value.fmt(f),
15751550
}
15761551
}

0 commit comments

Comments
 (0)