Skip to content

Commit 6fa059f

Browse files
committed
Make PyObject.typ a PyClassRef
1 parent 4666a09 commit 6fa059f

20 files changed

+154
-227
lines changed

src/main.rs

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,11 @@ fn main() {
6565
}
6666

6767
fn _run_string(vm: &VirtualMachine, source: &str, source_path: String) -> PyResult {
68-
let code_obj = compile::compile(
69-
source,
70-
&compile::Mode::Exec,
71-
source_path,
72-
vm.ctx.code_type(),
73-
)
74-
.map_err(|err| {
75-
let syntax_error = vm.context().exceptions.syntax_error.clone();
76-
vm.new_exception(syntax_error, err.to_string())
77-
})?;
68+
let code_obj =
69+
compile::compile(vm, source, &compile::Mode::Exec, source_path).map_err(|err| {
70+
let syntax_error = vm.context().exceptions.syntax_error.clone();
71+
vm.new_exception(syntax_error, err.to_string())
72+
})?;
7873
// trace!("Code object: {:?}", code_obj.borrow());
7974
let vars = vm.ctx.new_scope(); // Keep track of local variables
8075
vm.run_code_obj(code_obj, vars)
@@ -115,12 +110,7 @@ fn run_script(vm: &VirtualMachine, script_file: &str) -> PyResult {
115110
}
116111

117112
fn shell_exec(vm: &VirtualMachine, source: &str, scope: Scope) -> Result<(), CompileError> {
118-
match compile::compile(
119-
source,
120-
&compile::Mode::Single,
121-
"<stdin>".to_string(),
122-
vm.ctx.code_type(),
123-
) {
113+
match compile::compile(vm, source, &compile::Mode::Single, "<stdin>".to_string()) {
124114
Ok(code) => {
125115
if let Err(err) = vm.run_code_obj(code, scope) {
126116
print_exception(vm, &err);

vm/src/builtins.rs

Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use crate::pyobject::{
2424
};
2525
use crate::vm::VirtualMachine;
2626

27+
use crate::obj::objcode::PyCodeRef;
2728
#[cfg(not(target_arch = "wasm32"))]
2829
use crate::stdlib::io::io_open;
2930

@@ -112,22 +113,17 @@ fn builtin_chr(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
112113
Ok(vm.new_str(txt))
113114
}
114115

115-
fn builtin_compile(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
116-
arg_check!(
117-
vm,
118-
args,
119-
required = [
120-
(source, None),
121-
(filename, Some(vm.ctx.str_type())),
122-
(mode, Some(vm.ctx.str_type()))
123-
]
124-
);
125-
let source = objstr::get_value(source);
116+
fn builtin_compile(
117+
source: PyStringRef,
118+
filename: PyStringRef,
119+
mode: PyStringRef,
120+
vm: &VirtualMachine,
121+
) -> PyResult<PyCodeRef> {
126122
// TODO: fix this newline bug:
127-
let source = format!("{}\n", source);
123+
let source = format!("{}\n", &source.value);
128124

129125
let mode = {
130-
let mode = objstr::get_value(mode);
126+
let mode = &mode.value;
131127
if mode == "exec" {
132128
compile::Mode::Exec
133129
} else if mode == "eval" {
@@ -141,9 +137,7 @@ fn builtin_compile(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
141137
}
142138
};
143139

144-
let filename = objstr::get_value(filename);
145-
146-
compile::compile(&source, &mode, filename, vm.ctx.code_type()).map_err(|err| {
140+
compile::compile(vm, &source, &mode, filename.value.to_string()).map_err(|err| {
147141
let syntax_error = vm.context().exceptions.syntax_error.clone();
148142
vm.new_exception(syntax_error, err.to_string())
149143
})
@@ -190,25 +184,23 @@ fn builtin_eval(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
190184
let scope = make_scope(vm, globals, locals)?;
191185

192186
// Determine code object:
193-
let code_obj = if objtype::isinstance(source, &vm.ctx.code_type()) {
194-
source.clone()
187+
let code_obj = if let Ok(code_obj) = PyCodeRef::try_from_object(vm, source.clone()) {
188+
code_obj
195189
} else if objtype::isinstance(source, &vm.ctx.str_type()) {
196190
let mode = compile::Mode::Eval;
197191
let source = objstr::get_value(source);
198192
// TODO: fix this newline bug:
199193
let source = format!("{}\n", source);
200-
compile::compile(&source, &mode, "<string>".to_string(), vm.ctx.code_type()).map_err(
201-
|err| {
202-
let syntax_error = vm.context().exceptions.syntax_error.clone();
203-
vm.new_exception(syntax_error, err.to_string())
204-
},
205-
)?
194+
compile::compile(vm, &source, &mode, "<string>".to_string()).map_err(|err| {
195+
let syntax_error = vm.context().exceptions.syntax_error.clone();
196+
vm.new_exception(syntax_error, err.to_string())
197+
})?
206198
} else {
207199
return Err(vm.new_type_error("code argument must be str or code object".to_string()));
208200
};
209201

210202
// Run the source:
211-
vm.run_code_obj(code_obj.clone(), scope)
203+
vm.run_code_obj(code_obj, scope)
212204
}
213205

214206
/// Implements `exec`
@@ -229,14 +221,12 @@ fn builtin_exec(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
229221
let source = objstr::get_value(source);
230222
// TODO: fix this newline bug:
231223
let source = format!("{}\n", source);
232-
compile::compile(&source, &mode, "<string>".to_string(), vm.ctx.code_type()).map_err(
233-
|err| {
234-
let syntax_error = vm.context().exceptions.syntax_error.clone();
235-
vm.new_exception(syntax_error, err.to_string())
236-
},
237-
)?
238-
} else if objtype::isinstance(source, &vm.ctx.code_type()) {
239-
source.clone()
224+
compile::compile(vm, &source, &mode, "<string>".to_string()).map_err(|err| {
225+
let syntax_error = vm.context().exceptions.syntax_error.clone();
226+
vm.new_exception(syntax_error, err.to_string())
227+
})?
228+
} else if let Ok(code_obj) = PyCodeRef::try_from_object(vm, source.clone()) {
229+
code_obj
240230
} else {
241231
return Err(vm.new_type_error("source argument must be str or code object".to_string()));
242232
};

vm/src/compile.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
use crate::bytecode::{self, CallType, CodeObject, Instruction, Varargs};
99
use crate::error::CompileError;
1010
use crate::obj::objcode;
11-
use crate::obj::objtype::PyClassRef;
12-
use crate::pyobject::{PyObject, PyObjectRef};
11+
use crate::obj::objcode::PyCodeRef;
12+
use crate::pyobject::PyValue;
13+
use crate::VirtualMachine;
1314
use num_complex::Complex64;
1415
use rustpython_parser::{ast, parser};
1516

@@ -24,11 +25,11 @@ struct Compiler {
2425

2526
/// Compile a given sourcecode into a bytecode object.
2627
pub fn compile(
28+
vm: &VirtualMachine,
2729
source: &str,
2830
mode: &Mode,
2931
source_path: String,
30-
code_type: PyClassRef,
31-
) -> Result<PyObjectRef, CompileError> {
32+
) -> Result<PyCodeRef, CompileError> {
3233
let mut compiler = Compiler::new();
3334
compiler.source_path = Some(source_path);
3435
compiler.push_new_code_object("<module>".to_string());
@@ -50,10 +51,7 @@ pub fn compile(
5051

5152
let code = compiler.pop_code_object();
5253
trace!("Compilation completed: {:?}", code);
53-
Ok(PyObject::new(
54-
objcode::PyCode::new(code),
55-
code_type.into_object(),
56-
))
54+
Ok(objcode::PyCode::new(code).into_ref(vm))
5755
}
5856

5957
pub enum Mode {

vm/src/eval.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,7 @@ use crate::pyobject::PyResult;
88
use crate::vm::VirtualMachine;
99

1010
pub fn eval(vm: &VirtualMachine, source: &str, scope: Scope, source_path: &str) -> PyResult {
11-
match compile::compile(
12-
source,
13-
&compile::Mode::Eval,
14-
source_path.to_string(),
15-
vm.ctx.code_type(),
16-
) {
11+
match compile::compile(vm, source, &compile::Mode::Eval, source_path.to_string()) {
1712
Ok(bytecode) => {
1813
debug!("Code object: {:?}", bytecode);
1914
vm.run_code_obj(bytecode, scope)

vm/src/function.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,13 @@ pub enum OptionalArg<T> {
305305
}
306306

307307
impl<T> OptionalArg<T> {
308+
pub fn is_present(&self) -> bool {
309+
match self {
310+
Present(_) => true,
311+
Missing => false,
312+
}
313+
}
314+
308315
pub fn into_option(self) -> Option<T> {
309316
match self {
310317
Present(value) => Some(value),

vm/src/import.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ fn import_uncached_module(vm: &VirtualMachine, current_path: PathBuf, module: &s
2727
let source = util::read_file(file_path.as_path())
2828
.map_err(|e| vm.new_exception(import_error.clone(), e.description().to_string()))?;
2929
let code_obj = compile::compile(
30+
vm,
3031
&source,
3132
&compile::Mode::Exec,
3233
file_path.to_str().unwrap().to_string(),
33-
vm.ctx.code_type(),
3434
)
3535
.map_err(|err| {
3636
let syntax_error = vm.context().exceptions.syntax_error.clone();

vm/src/obj/objcode.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ use std::fmt;
77
use crate::bytecode;
88
use crate::function::PyFuncArgs;
99
use crate::obj::objtype::PyClassRef;
10-
use crate::pyobject::{IdProtocol, PyContext, PyObjectRef, PyResult, PyValue, TypeProtocol};
10+
use crate::pyobject::{IdProtocol, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol};
1111
use crate::vm::VirtualMachine;
1212

13+
pub type PyCodeRef = PyRef<PyCode>;
14+
1315
pub struct PyCode {
1416
code: bytecode::CodeObject,
1517
}

vm/src/obj/objfilter.rs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use crate::function::PyFuncArgs;
2-
use crate::pyobject::{
3-
IdProtocol, PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
4-
};
2+
use crate::pyobject::{IdProtocol, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol};
53
use crate::vm::VirtualMachine; // Required for arg_check! to use isinstance
64

75
use super::objbool;
86
use super::objiter;
97
use crate::obj::objtype::PyClassRef;
108

9+
pub type PyFilterRef = PyRef<PyFilter>;
10+
1111
#[derive(Debug)]
1212
pub struct PyFilter {
1313
predicate: PyObjectRef,
@@ -20,20 +20,19 @@ impl PyValue for PyFilter {
2020
}
2121
}
2222

23-
fn filter_new(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
24-
arg_check!(
25-
vm,
26-
args,
27-
required = [(cls, None), (function, None), (iterable, None)]
28-
);
29-
let iterator = objiter::get_iter(vm, iterable)?;
30-
Ok(PyObject::new(
31-
PyFilter {
32-
predicate: function.clone(),
33-
iterator,
34-
},
35-
cls.clone(),
36-
))
23+
fn filter_new(
24+
cls: PyClassRef,
25+
function: PyObjectRef,
26+
iterable: PyObjectRef,
27+
vm: &VirtualMachine,
28+
) -> PyResult<PyFilterRef> {
29+
let iterator = objiter::get_iter(vm, &iterable)?;
30+
31+
PyFilter {
32+
predicate: function.clone(),
33+
iterator,
34+
}
35+
.into_ref_with_type(vm, cls)
3736
}
3837

3938
fn filter_next(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {

vm/src/obj/objfloat.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use super::objstr;
44
use super::objtype;
55
use crate::obj::objtype::PyClassRef;
66
use crate::pyobject::{
7-
IntoPyObject, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
7+
IntoPyObject, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
88
};
99
use crate::vm::VirtualMachine;
1010
use num_bigint::ToBigInt;
@@ -155,7 +155,7 @@ impl PyFloatRef {
155155
}
156156
}
157157

158-
fn new_float(cls: PyObjectRef, arg: PyObjectRef, vm: &VirtualMachine) -> PyResult {
158+
fn new_float(cls: PyClassRef, arg: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyFloatRef> {
159159
let value = if objtype::isinstance(&arg, &vm.ctx.float_type()) {
160160
get_value(&arg)
161161
} else if objtype::isinstance(&arg, &vm.ctx.int_type()) {
@@ -193,7 +193,7 @@ impl PyFloatRef {
193193
let type_name = objtype::get_type_name(&arg.typ());
194194
return Err(vm.new_type_error(format!("can't convert {} to float", type_name)));
195195
};
196-
Ok(PyObject::new(PyFloat { value }, cls.clone()))
196+
PyFloat { value }.into_ref_with_type(vm, cls)
197197
}
198198

199199
fn mod_(self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {

vm/src/obj/objmemory.rs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
use crate::function::PyFuncArgs;
21
use crate::obj::objtype::PyClassRef;
3-
use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol};
2+
use crate::pyobject::{PyContext, PyObjectRef, PyRef, PyResult, PyValue};
43
use crate::vm::VirtualMachine;
54

5+
pub type PyMemoryViewRef = PyRef<PyMemoryView>;
6+
67
#[derive(Debug)]
78
pub struct PyMemoryView {
89
obj: PyObjectRef,
@@ -14,15 +15,13 @@ impl PyValue for PyMemoryView {
1415
}
1516
}
1617

17-
pub fn new_memory_view(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
18-
arg_check!(vm, args, required = [(cls, None), (bytes_object, None)]);
19-
vm.ctx.set_attr(cls, "obj", bytes_object.clone());
20-
Ok(PyObject::new(
21-
PyMemoryView {
22-
obj: bytes_object.clone(),
23-
},
24-
cls.clone(),
25-
))
18+
pub fn new_memory_view(
19+
cls: PyClassRef,
20+
bytes_object: PyObjectRef,
21+
vm: &VirtualMachine,
22+
) -> PyResult<PyMemoryViewRef> {
23+
vm.ctx.set_attr(&cls, "obj", bytes_object.clone());
24+
PyMemoryView { obj: bytes_object }.into_ref_with_type(vm, cls)
2625
}
2726

2827
pub fn init(ctx: &PyContext) {

vm/src/obj/objobject.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::obj::objproperty::PropertyBuilder;
77
use crate::obj::objtype::PyClassRef;
88
use crate::pyobject::{
99
DictProtocol, IdProtocol, PyAttributes, PyContext, PyObject, PyObjectRef, PyResult, PyValue,
10-
TypeProtocol,
10+
TryFromObject, TypeProtocol,
1111
};
1212
use crate::vm::VirtualMachine;
1313

@@ -22,7 +22,7 @@ impl PyValue for PyInstance {
2222

2323
pub fn new_instance(vm: &VirtualMachine, mut args: PyFuncArgs) -> PyResult {
2424
// more or less __new__ operator
25-
let cls = args.shift();
25+
let cls = PyClassRef::try_from_object(vm, args.shift())?;
2626
Ok(if cls.is(&vm.ctx.object) {
2727
PyObject::new_without_dict(PyInstance, cls)
2828
} else {

vm/src/obj/objproperty.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,15 +200,15 @@ impl<'a> PropertyBuilder<'a> {
200200
deleter: None,
201201
};
202202

203-
PyObject::new(payload, self.ctx.property_type().into_object())
203+
PyObject::new(payload, self.ctx.property_type())
204204
} else {
205205
let payload = PyReadOnlyProperty {
206206
getter: self.getter.expect(
207207
"One of add_getter/add_setter must be called when constructing a property",
208208
),
209209
};
210210

211-
PyObject::new(payload, self.ctx.readonly_property_type().into_object())
211+
PyObject::new(payload, self.ctx.readonly_property_type())
212212
}
213213
}
214214
}

vm/src/obj/objsequence.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,12 @@ pub fn get_item(
163163
if sequence.payload::<PyList>().is_some() {
164164
Ok(PyObject::new(
165165
PyList::from(elements.to_vec().get_slice_items(vm, &subscript)?),
166-
sequence.typ(),
166+
sequence.type_pyref(),
167167
))
168168
} else if sequence.payload::<PyTuple>().is_some() {
169169
Ok(PyObject::new(
170170
PyTuple::from(elements.to_vec().get_slice_items(vm, &subscript)?),
171-
sequence.typ(),
171+
sequence.type_pyref(),
172172
))
173173
} else {
174174
panic!("sequence get_item called for non-sequence")

0 commit comments

Comments
 (0)