diff --git a/vm/src/frame.rs b/vm/src/frame.rs index b1b7952e2..cd93e2ca9 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -70,7 +70,7 @@ impl Frame { // locals.extend(callargs); Frame { - code: objcode::copy_code(&code), + code: objcode::get_value(&code), stack: vec![], blocks: vec![], // save the callargs as locals diff --git a/vm/src/obj/objcode.rs b/vm/src/obj/objcode.rs index 54f10649b..5e86ea55d 100644 --- a/vm/src/obj/objcode.rs +++ b/vm/src/obj/objcode.rs @@ -4,7 +4,7 @@ use super::super::bytecode; use super::super::pyobject::{ - PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol, + IdProtocol, PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol, }; use super::super::vm::VirtualMachine; use super::objtype; @@ -18,15 +18,33 @@ pub fn init(context: &PyContext) { "co_argcount", context.new_member_descriptor(code_co_argcount), ); + context.set_attr( + code_type, + "co_cellvars", + context.new_member_descriptor(code_co_cellvars), + ); + context.set_attr( + code_type, + "co_consts", + context.new_member_descriptor(code_co_consts), + ); + context.set_attr( + code_type, + "co_filename", + context.new_member_descriptor(code_co_filename), + ); + context.set_attr( + code_type, + "co_firstlineno", + context.new_member_descriptor(code_co_firstlineno), + ); } -/// 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 PyObjectPayload::Code { ref code } = code_obj.payload { +pub fn get_value(obj: &PyObjectRef) -> bytecode::CodeObject { + if let PyObjectPayload::Code { code } = &obj.borrow().payload { code.clone() } else { - panic!("Must be code obj"); + panic!("Inner error getting code {:?}", obj) } } @@ -39,30 +57,24 @@ 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 code = get_value(o); - let file = if let Some(source_path) = code.source_path { - format!(", file {}", source_path) - } else { - String::new() - }; + let file = code.source_path.unwrap_or_else(|| String::new()); - // TODO: fetch proper line info from code object - let line = ", line 1".to_string(); - - let repr = format!("", file, line); + let repr = format!( + "", + code.obj_name, + o.get_id(), + file, + code.first_line_number + ); Ok(vm.new_str(repr)) } -fn get_value(obj: &PyObjectRef) -> bytecode::CodeObject { - if let PyObjectPayload::Code { code } = &obj.borrow().payload { - code.clone() - } else { - panic!("Inner error getting code {:?}", obj) - } -} - -fn code_co_argcount(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { +fn member_code_obj( + vm: &mut VirtualMachine, + args: PyFuncArgs, +) -> Result { arg_check!( vm, args, @@ -71,6 +83,31 @@ fn code_co_argcount(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { (_cls, Some(vm.ctx.type_type())) ] ); - let code_obj = get_value(zelf); + Ok(get_value(zelf)) +} + +fn code_co_argcount(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + let code_obj = member_code_obj(vm, args)?; Ok(vm.ctx.new_int(code_obj.arg_names.len())) } + +fn code_co_cellvars(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + let _code_obj = member_code_obj(vm, args)?; + Ok(vm.ctx.new_tuple(vec![])) +} + +fn code_co_consts(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + let _code_obj = member_code_obj(vm, args)?; + Ok(vm.ctx.new_tuple(vec![vm.get_none()])) +} + +fn code_co_filename(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + let code_obj = member_code_obj(vm, args)?; + let source_path = code_obj.source_path.unwrap_or_else(|| String::new()); + Ok(vm.new_str(source_path)) +} + +fn code_co_firstlineno(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + let code_obj = member_code_obj(vm, args)?; + Ok(vm.ctx.new_int(code_obj.first_line_number)) +} diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 435e7bcbc..cd7567c8e 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -11,7 +11,7 @@ use std::collections::hash_map::HashMap; use super::builtins; use super::bytecode; use super::frame::Frame; -use super::obj::objcode::copy_code; +use super::obj::objcode; use super::obj::objgenerator; use super::obj::objiter; use super::obj::objsequence; @@ -282,7 +282,7 @@ impl VirtualMachine { defaults: &PyObjectRef, args: PyFuncArgs, ) -> PyResult { - let code_object = copy_code(code); + let code_object = objcode::get_value(code); let scope = self.ctx.new_scope(Some(scope.clone())); self.fill_scope_from_args(&code_object, &scope, args, defaults)?;