diff --git a/vm/src/compile.rs b/vm/src/compile.rs index 6c17c0eb8..8aa37d550 100644 --- a/vm/src/compile.rs +++ b/vm/src/compile.rs @@ -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(), )) } diff --git a/vm/src/frame.rs b/vm/src/frame.rs index 76ae2c3f9..6f6cf292f 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -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 } => { diff --git a/vm/src/obj/mod.rs b/vm/src/obj/mod.rs index 8834262bd..96cebc802 100644 --- a/vm/src/obj/mod.rs +++ b/vm/src/obj/mod.rs @@ -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; diff --git a/vm/src/obj/objcode.rs b/vm/src/obj/objcode.rs new file mode 100644 index 000000000..1776c5a3b --- /dev/null +++ b/vm/src/obj/objcode.rs @@ -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!("", file, line); + Ok(vm.new_str(repr)) +} diff --git a/vm/src/obj/objframe.rs b/vm/src/obj/objframe.rs new file mode 100644 index 000000000..04c309613 --- /dev/null +++ b/vm/src/obj/objframe.rs @@ -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!(""); + Ok(vm.new_str(repr)) +} diff --git a/vm/src/obj/objsuper.rs b/vm/src/obj/objsuper.rs index 8c557453d..95ff56040 100644 --- a/vm/src/obj/objsuper.rs +++ b/vm/src/obj/objsuper.rs @@ -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() }; diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 842eecb6a..b65757714 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -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 { + // 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() } diff --git a/vm/src/stdlib/types.rs b/vm/src/stdlib/types.rs index 728b88c68..b005f3f3c 100644 --- a/vm/src/stdlib/types.rs +++ b/vm/src/stdlib/types.rs @@ -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 } diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 36027d768..41946a2de 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -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)?;