Add code and frame python objects.

This commit is contained in:
Windel Bouwman
2018-11-07 15:24:18 +01:00
parent df0400dffb
commit 4acea45f78
9 changed files with 144 additions and 47 deletions

View File

@@ -54,7 +54,7 @@ pub fn compile(
trace!("Compilation completed: {:?}", code);
Ok(PyObject::new(
PyObjectKind::Code { code: code },
vm.get_type(),
vm.ctx.code_type(),
))
}

View File

@@ -9,6 +9,7 @@ use super::builtins;
use super::bytecode;
use super::import::import;
use super::obj::objbool;
use super::obj::objcode;
use super::obj::objdict;
use super::obj::objiter;
use super::obj::objlist;
@@ -46,15 +47,6 @@ pub struct Frame {
pub lasti: usize, // index of last instruction ran
}
pub fn copy_code(code_obj: PyObjectRef) -> bytecode::CodeObject {
let code_obj = code_obj.borrow();
if let PyObjectKind::Code { ref code } = code_obj.kind {
code.clone()
} else {
panic!("Must be code obj");
}
}
// Running a frame can result in one of the below:
pub enum ExecutionResult {
Return(PyObjectRef),
@@ -78,7 +70,7 @@ impl Frame {
// locals.extend(callargs);
Frame {
code: copy_code(code),
code: objcode::copy_code(&code),
stack: vec![],
blocks: vec![],
// save the callargs as locals
@@ -302,8 +294,13 @@ impl Frame {
bytecode::Instruction::ListAppend { i } => {
let list_obj = self.nth_value(*i);
let item = self.pop_value();
// TODO: objlist::list_append()
vm.call_method(&list_obj, "append", vec![item])?;
objlist::list_append(
vm,
PyFuncArgs {
args: vec![list_obj.clone(), item],
kwargs: vec![],
},
)?;
Ok(None)
}
bytecode::Instruction::SetAdd { i } => {

View File

@@ -3,9 +3,11 @@
pub mod objbool;
pub mod objbytearray;
pub mod objbytes;
pub mod objcode;
pub mod objcomplex;
pub mod objdict;
pub mod objfloat;
pub mod objframe;
pub mod objfunction;
pub mod objgenerator;
pub mod objint;

44
vm/src/obj/objcode.rs Normal file
View File

@@ -0,0 +1,44 @@
/*! Infamous code object. The python class `code`
*/
use super::super::bytecode;
use super::super::pyobject::{
AttributeProtocol, PyContext, PyFuncArgs, PyObjectKind, PyObjectRef, PyResult, TypeProtocol,
};
use super::super::vm::VirtualMachine;
use super::objtype;
pub fn init(context: &PyContext) {
let ref code_type = context.code_type;
code_type.set_attr("__repr__", context.new_rustfunc(code_repr));
}
/// Extract rust bytecode object from a python code object.
pub fn copy_code(code_obj: &PyObjectRef) -> bytecode::CodeObject {
let code_obj = code_obj.borrow();
if let PyObjectKind::Code { ref code } = code_obj.kind {
code.clone()
} else {
panic!("Must be code obj");
}
}
fn code_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(o, Some(vm.ctx.code_type()))]);
// Fetch actual code:
let code = copy_code(o);
let file = if let Some(source_path) = code.source_path {
format!(", file {}", source_path)
} else {
String::new()
};
// TODO: fetch proper line info from code object
let line = format!(", line 1");
let repr = format!("<code object at .. {}{}>", file, line);
Ok(vm.new_str(repr))
}

20
vm/src/obj/objframe.rs Normal file
View File

@@ -0,0 +1,20 @@
/*! The python `frame` type.
*/
use super::super::pyobject::{
AttributeProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol,
};
use super::super::vm::VirtualMachine;
use super::objtype;
pub fn init(context: &PyContext) {
let ref frame_type = context.frame_type;
frame_type.set_attr("__repr__", context.new_rustfunc(frame_repr));
}
fn frame_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(_frame, Some(vm.ctx.frame_type()))]);
let repr = format!("<frame object at .. >");
Ok(vm.new_str(repr))
}

View File

@@ -32,6 +32,8 @@ fn super_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
} else {
// TODO: implement complex logic here....
unimplemented!("TODO: get frame and determine instance and class?");
// let frame = vm.get_current_frame();
//
// vm.get_none()
};

View File

@@ -4,9 +4,11 @@ use super::frame::Frame;
use super::obj::objbool;
use super::obj::objbytearray;
use super::obj::objbytes;
use super::obj::objcode;
use super::obj::objcomplex;
use super::obj::objdict;
use super::obj::objfloat;
use super::obj::objframe;
use super::obj::objfunction;
use super::obj::objgenerator;
use super::obj::objint;
@@ -70,31 +72,44 @@ impl fmt::Display for PyObjectRef {
}
}*/
/*
// Idea: implement the iterator trait upon PyObjectRef
impl Iterator for (VirtualMachine, PyObjectRef) {
type Item = char;
fn next(&mut self) -> Option<Self::Item> {
// call method ("_next__")
}
}
*/
#[derive(Debug)]
pub struct PyContext {
pub type_type: PyObjectRef,
pub none: PyObjectRef,
pub classmethod_type: PyObjectRef,
pub staticmethod_type: PyObjectRef,
pub dict_type: PyObjectRef,
pub int_type: PyObjectRef,
pub float_type: PyObjectRef,
pub complex_type: PyObjectRef,
pub bytes_type: PyObjectRef,
pub bytearray_type: PyObjectRef,
pub bool_type: PyObjectRef,
pub classmethod_type: PyObjectRef,
pub code_type: PyObjectRef,
pub dict_type: PyObjectRef,
pub float_type: PyObjectRef,
pub frame_type: PyObjectRef,
pub frozenset_type: PyObjectRef,
pub generator_type: PyObjectRef,
pub int_type: PyObjectRef,
pub iter_type: PyObjectRef,
pub complex_type: PyObjectRef,
pub true_value: PyObjectRef,
pub false_value: PyObjectRef,
pub list_type: PyObjectRef,
pub none: PyObjectRef,
pub tuple_type: PyObjectRef,
pub set_type: PyObjectRef,
pub frozenset_type: PyObjectRef,
pub iter_type: PyObjectRef,
pub staticmethod_type: PyObjectRef,
pub super_type: PyObjectRef,
pub str_type: PyObjectRef,
pub type_type: PyObjectRef,
pub function_type: PyObjectRef,
pub property_type: PyObjectRef,
pub generator_type: PyObjectRef,
pub module_type: PyObjectRef,
pub bound_method_type: PyObjectRef,
pub member_descriptor_type: PyObjectRef,
@@ -162,12 +177,14 @@ impl PyContext {
let frozenset_type = create_type("frozenset", &type_type, &object_type, &dict_type);
let int_type = create_type("int", &type_type, &object_type, &dict_type);
let float_type = create_type("float", &type_type, &object_type, &dict_type);
let frame_type = create_type("frame", &type_type, &object_type, &dict_type);
let complex_type = create_type("complex", &type_type, &object_type, &dict_type);
let bytes_type = create_type("bytes", &type_type, &object_type, &dict_type);
let bytearray_type = create_type("bytearray", &type_type, &object_type, &dict_type);
let tuple_type = create_type("tuple", &type_type, &object_type, &dict_type);
let iter_type = create_type("iter", &type_type, &object_type, &dict_type);
let bool_type = create_type("bool", &type_type, &int_type, &dict_type);
let code_type = create_type("code", &type_type, &int_type, &dict_type);
let exceptions = exceptions::ExceptionZoo::new(&type_type, &object_type, &dict_type);
let none = PyObject::new(
@@ -186,17 +203,19 @@ impl PyContext {
bool_type.clone(),
);
let context = PyContext {
int_type: int_type,
float_type: float_type,
bool_type: bool_type,
bytearray_type: bytearray_type,
bytes_type: bytes_type,
code_type: code_type,
complex_type: complex_type,
classmethod_type: classmethod_type,
int_type: int_type,
float_type: float_type,
frame_type: frame_type,
staticmethod_type: staticmethod_type,
bytes_type: bytes_type,
bytearray_type: bytearray_type,
list_type: list_type,
set_type: set_type,
frozenset_type: frozenset_type,
bool_type: bool_type,
true_value: true_value,
false_value: false_value,
tuple_type: tuple_type,
@@ -234,28 +253,42 @@ impl PyContext {
objtuple::init(&context);
objiter::init(&context);
objbool::init(&context);
objcode::init(&context);
objframe::init(&context);
exceptions::init(&context);
context
}
pub fn int_type(&self) -> PyObjectRef {
self.int_type.clone()
}
pub fn float_type(&self) -> PyObjectRef {
self.float_type.clone()
}
pub fn complex_type(&self) -> PyObjectRef {
self.complex_type.clone()
pub fn bytearray_type(&self) -> PyObjectRef {
self.bytearray_type.clone()
}
pub fn bytes_type(&self) -> PyObjectRef {
self.bytes_type.clone()
}
pub fn bytearray_type(&self) -> PyObjectRef {
self.bytearray_type.clone()
pub fn code_type(&self) -> PyObjectRef {
self.code_type.clone()
}
pub fn complex_type(&self) -> PyObjectRef {
self.complex_type.clone()
}
pub fn dict_type(&self) -> PyObjectRef {
self.dict_type.clone()
}
pub fn float_type(&self) -> PyObjectRef {
self.float_type.clone()
}
pub fn frame_type(&self) -> PyObjectRef {
self.frame_type.clone()
}
pub fn int_type(&self) -> PyObjectRef {
self.int_type.clone()
}
pub fn list_type(&self) -> PyObjectRef {
@@ -282,10 +315,6 @@ impl PyContext {
self.iter_type.clone()
}
pub fn dict_type(&self) -> PyObjectRef {
self.dict_type.clone()
}
pub fn str_type(&self) -> PyObjectRef {
self.str_type.clone()
}

View File

@@ -40,6 +40,8 @@ pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
py_mod.set_item("new_class", ctx.new_rustfunc(types_new_class));
py_mod.set_item("FunctionType", ctx.function_type());
py_mod.set_item("LambdaType", ctx.function_type());
py_mod.set_item("CodeType", ctx.code_type());
py_mod.set_item("FrameType", ctx.frame_type());
py_mod
}

View File

@@ -10,7 +10,8 @@ use std::collections::hash_map::HashMap;
use super::builtins;
use super::bytecode;
use super::frame::{copy_code, Frame};
use super::frame::Frame;
use super::obj::objcode::copy_code;
use super::obj::objgenerator;
use super::obj::objiter;
use super::obj::objsequence;
@@ -252,7 +253,7 @@ impl VirtualMachine {
defaults: &PyObjectRef,
args: PyFuncArgs,
) -> PyResult {
let code_object = copy_code(code.clone());
let code_object = copy_code(code);
let scope = self.ctx.new_scope(Some(scope.clone()));
self.fill_scope_from_args(&code_object, &scope, args, defaults)?;