Skip to content

Commit 4acea45

Browse files
committed
Add code and frame python objects.
1 parent df0400d commit 4acea45

File tree

9 files changed

+139
-42
lines changed

9 files changed

+139
-42
lines changed

vm/src/compile.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ pub fn compile(
5454
trace!("Compilation completed: {:?}", code);
5555
Ok(PyObject::new(
5656
PyObjectKind::Code { code: code },
57-
vm.get_type(),
57+
vm.ctx.code_type(),
5858
))
5959
}
6060

vm/src/frame.rs

+9-12
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use super::builtins;
99
use super::bytecode;
1010
use super::import::import;
1111
use super::obj::objbool;
12+
use super::obj::objcode;
1213
use super::obj::objdict;
1314
use super::obj::objiter;
1415
use super::obj::objlist;
@@ -46,15 +47,6 @@ pub struct Frame {
4647
pub lasti: usize, // index of last instruction ran
4748
}
4849

49-
pub fn copy_code(code_obj: PyObjectRef) -> bytecode::CodeObject {
50-
let code_obj = code_obj.borrow();
51-
if let PyObjectKind::Code { ref code } = code_obj.kind {
52-
code.clone()
53-
} else {
54-
panic!("Must be code obj");
55-
}
56-
}
57-
5850
// Running a frame can result in one of the below:
5951
pub enum ExecutionResult {
6052
Return(PyObjectRef),
@@ -78,7 +70,7 @@ impl Frame {
7870
// locals.extend(callargs);
7971

8072
Frame {
81-
code: copy_code(code),
73+
code: objcode::copy_code(&code),
8274
stack: vec![],
8375
blocks: vec![],
8476
// save the callargs as locals
@@ -302,8 +294,13 @@ impl Frame {
302294
bytecode::Instruction::ListAppend { i } => {
303295
let list_obj = self.nth_value(*i);
304296
let item = self.pop_value();
305-
// TODO: objlist::list_append()
306-
vm.call_method(&list_obj, "append", vec![item])?;
297+
objlist::list_append(
298+
vm,
299+
PyFuncArgs {
300+
args: vec![list_obj.clone(), item],
301+
kwargs: vec![],
302+
},
303+
)?;
307304
Ok(None)
308305
}
309306
bytecode::Instruction::SetAdd { i } => {

vm/src/obj/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
pub mod objbool;
44
pub mod objbytearray;
55
pub mod objbytes;
6+
pub mod objcode;
67
pub mod objcomplex;
78
pub mod objdict;
89
pub mod objfloat;
10+
pub mod objframe;
911
pub mod objfunction;
1012
pub mod objgenerator;
1113
pub mod objint;

vm/src/obj/objcode.rs

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*! Infamous code object. The python class `code`
2+
3+
*/
4+
5+
use super::super::bytecode;
6+
use super::super::pyobject::{
7+
AttributeProtocol, PyContext, PyFuncArgs, PyObjectKind, PyObjectRef, PyResult, TypeProtocol,
8+
};
9+
use super::super::vm::VirtualMachine;
10+
use super::objtype;
11+
12+
pub fn init(context: &PyContext) {
13+
let ref code_type = context.code_type;
14+
code_type.set_attr("__repr__", context.new_rustfunc(code_repr));
15+
}
16+
17+
/// Extract rust bytecode object from a python code object.
18+
pub fn copy_code(code_obj: &PyObjectRef) -> bytecode::CodeObject {
19+
let code_obj = code_obj.borrow();
20+
if let PyObjectKind::Code { ref code } = code_obj.kind {
21+
code.clone()
22+
} else {
23+
panic!("Must be code obj");
24+
}
25+
}
26+
27+
fn code_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
28+
arg_check!(vm, args, required = [(o, Some(vm.ctx.code_type()))]);
29+
30+
// Fetch actual code:
31+
let code = copy_code(o);
32+
33+
let file = if let Some(source_path) = code.source_path {
34+
format!(", file {}", source_path)
35+
} else {
36+
String::new()
37+
};
38+
39+
// TODO: fetch proper line info from code object
40+
let line = format!(", line 1");
41+
42+
let repr = format!("<code object at .. {}{}>", file, line);
43+
Ok(vm.new_str(repr))
44+
}

vm/src/obj/objframe.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*! The python `frame` type.
2+
3+
*/
4+
5+
use super::super::pyobject::{
6+
AttributeProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol,
7+
};
8+
use super::super::vm::VirtualMachine;
9+
use super::objtype;
10+
11+
pub fn init(context: &PyContext) {
12+
let ref frame_type = context.frame_type;
13+
frame_type.set_attr("__repr__", context.new_rustfunc(frame_repr));
14+
}
15+
16+
fn frame_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
17+
arg_check!(vm, args, required = [(_frame, Some(vm.ctx.frame_type()))]);
18+
let repr = format!("<frame object at .. >");
19+
Ok(vm.new_str(repr))
20+
}

vm/src/obj/objsuper.rs

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ fn super_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
3232
} else {
3333
// TODO: implement complex logic here....
3434
unimplemented!("TODO: get frame and determine instance and class?");
35+
// let frame = vm.get_current_frame();
36+
//
3537
// vm.get_none()
3638
};
3739

vm/src/pyobject.rs

+56-27
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ use super::frame::Frame;
44
use super::obj::objbool;
55
use super::obj::objbytearray;
66
use super::obj::objbytes;
7+
use super::obj::objcode;
78
use super::obj::objcomplex;
89
use super::obj::objdict;
910
use super::obj::objfloat;
11+
use super::obj::objframe;
1012
use super::obj::objfunction;
1113
use super::obj::objgenerator;
1214
use super::obj::objint;
@@ -70,31 +72,44 @@ impl fmt::Display for PyObjectRef {
7072
}
7173
}*/
7274

75+
/*
76+
// Idea: implement the iterator trait upon PyObjectRef
77+
impl Iterator for (VirtualMachine, PyObjectRef) {
78+
type Item = char;
79+
80+
fn next(&mut self) -> Option<Self::Item> {
81+
// call method ("_next__")
82+
}
83+
}
84+
*/
85+
7386
#[derive(Debug)]
7487
pub struct PyContext {
75-
pub type_type: PyObjectRef,
76-
pub none: PyObjectRef,
88+
pub bytes_type: PyObjectRef,
89+
pub bytearray_type: PyObjectRef,
90+
pub bool_type: PyObjectRef,
7791
pub classmethod_type: PyObjectRef,
78-
pub staticmethod_type: PyObjectRef,
92+
pub code_type: PyObjectRef,
7993
pub dict_type: PyObjectRef,
80-
pub int_type: PyObjectRef,
8194
pub float_type: PyObjectRef,
95+
pub frame_type: PyObjectRef,
96+
pub frozenset_type: PyObjectRef,
97+
pub generator_type: PyObjectRef,
98+
pub int_type: PyObjectRef,
99+
pub iter_type: PyObjectRef,
82100
pub complex_type: PyObjectRef,
83-
pub bytes_type: PyObjectRef,
84-
pub bytearray_type: PyObjectRef,
85-
pub bool_type: PyObjectRef,
86101
pub true_value: PyObjectRef,
87102
pub false_value: PyObjectRef,
88103
pub list_type: PyObjectRef,
104+
pub none: PyObjectRef,
89105
pub tuple_type: PyObjectRef,
90106
pub set_type: PyObjectRef,
91-
pub frozenset_type: PyObjectRef,
92-
pub iter_type: PyObjectRef,
107+
pub staticmethod_type: PyObjectRef,
93108
pub super_type: PyObjectRef,
94109
pub str_type: PyObjectRef,
110+
pub type_type: PyObjectRef,
95111
pub function_type: PyObjectRef,
96112
pub property_type: PyObjectRef,
97-
pub generator_type: PyObjectRef,
98113
pub module_type: PyObjectRef,
99114
pub bound_method_type: PyObjectRef,
100115
pub member_descriptor_type: PyObjectRef,
@@ -162,12 +177,14 @@ impl PyContext {
162177
let frozenset_type = create_type("frozenset", &type_type, &object_type, &dict_type);
163178
let int_type = create_type("int", &type_type, &object_type, &dict_type);
164179
let float_type = create_type("float", &type_type, &object_type, &dict_type);
180+
let frame_type = create_type("frame", &type_type, &object_type, &dict_type);
165181
let complex_type = create_type("complex", &type_type, &object_type, &dict_type);
166182
let bytes_type = create_type("bytes", &type_type, &object_type, &dict_type);
167183
let bytearray_type = create_type("bytearray", &type_type, &object_type, &dict_type);
168184
let tuple_type = create_type("tuple", &type_type, &object_type, &dict_type);
169185
let iter_type = create_type("iter", &type_type, &object_type, &dict_type);
170186
let bool_type = create_type("bool", &type_type, &int_type, &dict_type);
187+
let code_type = create_type("code", &type_type, &int_type, &dict_type);
171188
let exceptions = exceptions::ExceptionZoo::new(&type_type, &object_type, &dict_type);
172189

173190
let none = PyObject::new(
@@ -186,17 +203,19 @@ impl PyContext {
186203
bool_type.clone(),
187204
);
188205
let context = PyContext {
189-
int_type: int_type,
190-
float_type: float_type,
206+
bool_type: bool_type,
207+
bytearray_type: bytearray_type,
208+
bytes_type: bytes_type,
209+
code_type: code_type,
191210
complex_type: complex_type,
192211
classmethod_type: classmethod_type,
212+
int_type: int_type,
213+
float_type: float_type,
214+
frame_type: frame_type,
193215
staticmethod_type: staticmethod_type,
194-
bytes_type: bytes_type,
195-
bytearray_type: bytearray_type,
196216
list_type: list_type,
197217
set_type: set_type,
198218
frozenset_type: frozenset_type,
199-
bool_type: bool_type,
200219
true_value: true_value,
201220
false_value: false_value,
202221
tuple_type: tuple_type,
@@ -234,28 +253,42 @@ impl PyContext {
234253
objtuple::init(&context);
235254
objiter::init(&context);
236255
objbool::init(&context);
256+
objcode::init(&context);
257+
objframe::init(&context);
237258
exceptions::init(&context);
238259
context
239260
}
240261

241-
pub fn int_type(&self) -> PyObjectRef {
242-
self.int_type.clone()
262+
pub fn bytearray_type(&self) -> PyObjectRef {
263+
self.bytearray_type.clone()
243264
}
244265

245-
pub fn float_type(&self) -> PyObjectRef {
246-
self.float_type.clone()
266+
pub fn bytes_type(&self) -> PyObjectRef {
267+
self.bytes_type.clone()
268+
}
269+
270+
pub fn code_type(&self) -> PyObjectRef {
271+
self.code_type.clone()
247272
}
248273

249274
pub fn complex_type(&self) -> PyObjectRef {
250275
self.complex_type.clone()
251276
}
252277

253-
pub fn bytes_type(&self) -> PyObjectRef {
254-
self.bytes_type.clone()
278+
pub fn dict_type(&self) -> PyObjectRef {
279+
self.dict_type.clone()
255280
}
256281

257-
pub fn bytearray_type(&self) -> PyObjectRef {
258-
self.bytearray_type.clone()
282+
pub fn float_type(&self) -> PyObjectRef {
283+
self.float_type.clone()
284+
}
285+
286+
pub fn frame_type(&self) -> PyObjectRef {
287+
self.frame_type.clone()
288+
}
289+
290+
pub fn int_type(&self) -> PyObjectRef {
291+
self.int_type.clone()
259292
}
260293

261294
pub fn list_type(&self) -> PyObjectRef {
@@ -282,10 +315,6 @@ impl PyContext {
282315
self.iter_type.clone()
283316
}
284317

285-
pub fn dict_type(&self) -> PyObjectRef {
286-
self.dict_type.clone()
287-
}
288-
289318
pub fn str_type(&self) -> PyObjectRef {
290319
self.str_type.clone()
291320
}

vm/src/stdlib/types.rs

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
4040
py_mod.set_item("new_class", ctx.new_rustfunc(types_new_class));
4141
py_mod.set_item("FunctionType", ctx.function_type());
4242
py_mod.set_item("LambdaType", ctx.function_type());
43+
py_mod.set_item("CodeType", ctx.code_type());
44+
py_mod.set_item("FrameType", ctx.frame_type());
4345

4446
py_mod
4547
}

vm/src/vm.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ use std::collections::hash_map::HashMap;
1010

1111
use super::builtins;
1212
use super::bytecode;
13-
use super::frame::{copy_code, Frame};
13+
use super::frame::Frame;
14+
use super::obj::objcode::copy_code;
1415
use super::obj::objgenerator;
1516
use super::obj::objiter;
1617
use super::obj::objsequence;
@@ -252,7 +253,7 @@ impl VirtualMachine {
252253
defaults: &PyObjectRef,
253254
args: PyFuncArgs,
254255
) -> PyResult {
255-
let code_object = copy_code(code.clone());
256+
let code_object = copy_code(code);
256257
let scope = self.ctx.new_scope(Some(scope.clone()));
257258
self.fill_scope_from_args(&code_object, &scope, args, defaults)?;
258259

0 commit comments

Comments
 (0)