diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index d1bbc7477..f722a82f8 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -4,15 +4,15 @@ use std::io::{self, Write}; use super::compile; use super::pyobject::DictProtocol; -use super::pyobject::{PyContext, PyObject, PyObjectKind, PyObjectRef, PyResult, Scope, IdProtocol}; +use super::pyobject::{PyContext, PyObject, PyObjectKind, PyObjectRef, PyResult, Scope, IdProtocol, PyFuncArgs}; use super::vm::VirtualMachine; use super::objbool; -fn get_locals(rt: &mut VirtualMachine) -> PyObjectRef { - let mut d = rt.new_dict(); +fn get_locals(vm: &mut VirtualMachine) -> PyObjectRef { + let mut d = vm.new_dict(); // TODO: implement dict_iter_items? - let locals = rt.get_locals(); + let locals = vm.get_locals(); match locals.borrow().kind { PyObjectKind::Dict { ref elements } => { for l in elements { @@ -24,63 +24,64 @@ fn get_locals(rt: &mut VirtualMachine) -> PyObjectRef { d } -fn dir_locals(rt: &mut VirtualMachine) -> PyObjectRef { - get_locals(rt) +fn dir_locals(vm: &mut VirtualMachine) -> PyObjectRef { + get_locals(vm) } -fn dir_object(rt: &mut VirtualMachine, obj: PyObjectRef) -> PyObjectRef { - let d = rt.new_dict(); +fn dir_object(vm: &mut VirtualMachine, obj: PyObjectRef) -> PyObjectRef { + let d = vm.new_dict(); d } -pub fn builtin_dir(rt: &mut VirtualMachine, args: Vec) -> PyResult { - if args.is_empty() { - Ok(dir_locals(rt)) +pub fn builtin_dir(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + if args.args.is_empty() { + Ok(dir_locals(vm)) } else { - let obj = args.into_iter().next().unwrap(); - Ok(dir_object(rt, obj)) + let obj = args.args.into_iter().next().unwrap(); + Ok(dir_object(vm, obj)) } } -pub fn builtin_id(rt: &mut VirtualMachine, args: Vec) -> PyResult { - if args.len() != 1 { - return Err(rt.new_exception("Expected only one argument".to_string())) +pub fn builtin_id(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + if args.args.len() != 1 { + return Err(vm.new_exception("Expected only one argument".to_string())) } - Ok(rt.context().new_int(args[0].get_id() as i32)) + Ok(vm.context().new_int(args.args[0].get_id() as i32)) } -pub fn builtin_print(rt: &mut VirtualMachine, args: Vec) -> PyResult { +pub fn builtin_print(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { trace!("print called with {:?}", args); - for a in args { + for a in args.args { print!("{} ", a.borrow().str()); } println!(); io::stdout().flush().unwrap(); - Ok(rt.get_none()) + Ok(vm.get_none()) } -pub fn builtin_compile(rt: &mut VirtualMachine, args: Vec) -> PyResult { - if args.len() < 1 { - return Err(rt.new_exception("Expected more arguments".to_string())) +pub fn builtin_compile(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + if args.args.len() < 1 { + return Err(vm.new_exception("Expected more arguments".to_string())) } // TODO: let mode = compile::Mode::Eval; - let source = args[0].borrow().str(); + let source = args.args[0].borrow().str(); - match compile::compile(rt, &source, mode) { + match compile::compile(vm, &source, mode) { Ok(value) => Ok(value), - Err(msg) => Err(rt.new_exception(msg)), + Err(msg) => Err(vm.new_exception(msg)), } } -pub fn builtin_eval(rt: &mut VirtualMachine, args: Vec) -> PyResult { +pub fn builtin_eval(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + let args = args.args; if args.len() > 3 { - return Err(rt.new_exception("Expected at maximum of 3 arguments".to_string())) + return Err(vm.new_exception("Expected at maximum of 3 arguments".to_string())) } else if args.len() > 2 { // TODO: handle optional global and locals } else { - return Err(rt.new_exception("Expected at least one argument".to_string())) + return Err(vm.new_exception("Expected at least one argument".to_string())) } let source = args[0].clone(); let _globals = args[1].clone(); @@ -96,27 +97,27 @@ pub fn builtin_eval(rt: &mut VirtualMachine, args: Vec) -> PyResult let scope = PyObject { kind: PyObjectKind::Scope { scope: scope_inner }, typ: None }.into_ref(); // Run the source: - rt.run_code_obj(code_obj, scope) + vm.run_code_obj(code_obj, scope) } -pub fn locals(rt: &mut VirtualMachine, args: Vec) -> PyResult { - Ok(rt.get_locals()) +pub fn builtin_locals(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + Ok(vm.get_locals()) } -pub fn len(rt: &mut VirtualMachine, args: Vec) -> PyResult { - if args.len() != 1 { +pub fn builtin_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + if args.args.len() != 1 { panic!("len(s) expects exactly one parameter"); } - let len = match args[0].borrow().kind { + let len = match args.args[0].borrow().kind { PyObjectKind::List { ref elements } => elements.len(), PyObjectKind::Tuple { ref elements } => elements.len(), PyObjectKind::String { ref value } => value.len(), _ => { - return Err(rt.context() + return Err(vm.context() .new_str("TypeError: object of this type has no len()".to_string())) } }; - Ok(rt.context().new_int(len as i32)) + Ok(vm.context().new_int(len as i32)) } pub fn make_module(ctx: &PyContext) -> PyObjectRef { @@ -129,10 +130,10 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef { dict.insert(String::from("all"), ctx.new_rustfunc(builtin_all)); dict.insert(String::from("any"), ctx.new_rustfunc(builtin_any)); dict.insert(String::from("dir"), ctx.new_rustfunc(builtin_dir)); - dict.insert(String::from("locals"), ctx.new_rustfunc(locals)); + dict.insert(String::from("locals"), ctx.new_rustfunc(builtin_locals)); dict.insert(String::from("compile"), ctx.new_rustfunc(builtin_compile)); dict.insert(String::from("eval"), ctx.new_rustfunc(builtin_eval)); - dict.insert("len".to_string(), ctx.new_rustfunc(len)); + dict.insert("len".to_string(), ctx.new_rustfunc(builtin_len)); let d2 = PyObject::new(PyObjectKind::Dict { elements: dict }, ctx.type_type.clone()); let scope = PyObject::new(PyObjectKind::Scope { scope: Scope { locals: d2, parent: None} }, ctx.type_type.clone()); let obj = PyObject::new( @@ -145,10 +146,10 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef { obj } -fn builtin_any(rt: &mut VirtualMachine, args: Vec) -> PyResult { - Ok(rt.new_bool(args.into_iter().any(|e| objbool::boolval(e)))) +fn builtin_any(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + Ok(vm.new_bool(args.args.into_iter().any(|e| objbool::boolval(e)))) } -fn builtin_all(rt: &mut VirtualMachine, args: Vec) -> PyResult { - Ok(rt.new_bool(args.into_iter().all(|e| objbool::boolval(e)))) +fn builtin_all(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + Ok(vm.new_bool(args.args.into_iter().all(|e| objbool::boolval(e)))) } diff --git a/vm/src/compile.rs b/vm/src/compile.rs index f614afdae..6fade2beb 100644 --- a/vm/src/compile.rs +++ b/vm/src/compile.rs @@ -14,7 +14,7 @@ struct Compiler { nxt_label: usize, } -pub fn compile(rt: &mut VirtualMachine, source: &String, mode: Mode) -> Result { +pub fn compile(vm: &mut VirtualMachine, source: &String, mode: Mode) -> Result { let mut compiler = Compiler::new(); compiler.push_code_object(CodeObject::new(Vec::new())); match mode { @@ -43,7 +43,7 @@ pub fn compile(rt: &mut VirtualMachine, source: &String, mode: Mode) -> Result

PyResult { - Ok(rt.get_none()) +pub fn set_item(vm: &mut VirtualMachine, d: PyObjectRef, idx: PyObjectRef, obj: PyObjectRef) -> PyResult { + Ok(vm.get_none()) } /* TODO: diff --git a/vm/src/objint.rs b/vm/src/objint.rs index 8796adb5b..d15f0fe65 100644 --- a/vm/src/objint.rs +++ b/vm/src/objint.rs @@ -1,9 +1,9 @@ -use super::pyobject::{PyObject, PyObjectKind, PyObjectRef}; +use super::pyobject::{PyObject, PyObjectKind, PyObjectRef, PyFuncArgs}; use super::vm::VirtualMachine; use std::collections::HashMap; -fn str(rt: &mut VirtualMachine, args: Vec) -> Result { - Ok(rt.new_str("todo".to_string())) +fn str(vm: &mut VirtualMachine, args: PyFuncArgs) -> Result { + Ok(vm.new_str("todo".to_string())) } fn add() {} diff --git a/vm/src/objlist.rs b/vm/src/objlist.rs index 16f3a83eb..8379f0437 100644 --- a/vm/src/objlist.rs +++ b/vm/src/objlist.rs @@ -9,7 +9,7 @@ fn get_pos(l: &Vec, p: i32) -> usize { } } -pub fn get_item(rt: &mut VirtualMachine, l: &Vec, b: PyObjectRef) -> PyResult { +pub fn get_item(vm: &mut VirtualMachine, l: &Vec, b: PyObjectRef) -> PyResult { match &(b.borrow()).kind { PyObjectKind::Integer { value } => { let pos_index = get_pos(l, *value); @@ -17,7 +17,7 @@ pub fn get_item(rt: &mut VirtualMachine, l: &Vec, b: PyObjectRef) - let obj = l[pos_index].clone(); Ok(obj) } else { - Err(rt.new_exception("Index out of bounds!".to_string())) + Err(vm.new_exception("Index out of bounds!".to_string())) } } PyObjectKind::Slice { start, stop, step } => { @@ -39,11 +39,11 @@ pub fn get_item(rt: &mut VirtualMachine, l: &Vec, b: PyObjectRef) - PyObjectKind::List { elements: l[start..stop].to_vec(), }, - rt.get_type(), + vm.get_type(), ); Ok(obj) } - _ => Err(rt.new_exception(format!( + _ => Err(vm.new_exception(format!( "TypeError: indexing type {:?} with index {:?} is not supported (yet?)", l, b ))), @@ -52,7 +52,7 @@ pub fn get_item(rt: &mut VirtualMachine, l: &Vec, b: PyObjectRef) - // set_item: pub fn set_item( - rt: &mut VirtualMachine, + vm: &mut VirtualMachine, l: &mut Vec, idx: PyObjectRef, obj: PyObjectRef, @@ -61,7 +61,7 @@ pub fn set_item( PyObjectKind::Integer { value } => { let pos_index = get_pos(l, *value); l[pos_index] = obj; - Ok(rt.get_none()) + Ok(vm.get_none()) } _ => panic!( "TypeError: indexing type {:?} with index {:?} is not supported (yet?)", @@ -70,8 +70,8 @@ pub fn set_item( } } -pub fn append(rt: &mut VirtualMachine, l: PyObjectRef, other: PyObjectRef) -> PyResult { - Ok(rt.get_none()) +pub fn append(vm: &mut VirtualMachine, l: PyObjectRef, other: PyObjectRef) -> PyResult { + Ok(vm.get_none()) } /* TODO: diff --git a/vm/src/objstr.rs b/vm/src/objstr.rs index a91581894..01fde74e0 100644 --- a/vm/src/objstr.rs +++ b/vm/src/objstr.rs @@ -11,12 +11,12 @@ fn str_pos(s: &String, p: i32) -> usize { } } -pub fn subscript(rt: &mut VirtualMachine, value: &String, b: PyObjectRef) -> PyResult { +pub fn subscript(vm: &mut VirtualMachine, value: &String, b: PyObjectRef) -> PyResult { // let value = a match &(*b.borrow()).kind { &PyObjectKind::Integer { value: ref pos } => { let idx = str_pos(value, *pos); - Ok(rt.new_str(value[idx..idx + 1].to_string())) + Ok(vm.new_str(value[idx..idx + 1].to_string())) } &PyObjectKind::Slice { ref start, @@ -38,7 +38,7 @@ pub fn subscript(rt: &mut VirtualMachine, value: &String, b: PyObjectRef) -> PyR &None => 1 as usize, _ => unimplemented!(), }; - Ok(rt.new_str(value[start2..stop2].to_string())) + Ok(vm.new_str(value[start2..stop2].to_string())) } _ => panic!( "TypeError: indexing type {:?} with index {:?} is not supported (yet?)", diff --git a/vm/src/objtuple.rs b/vm/src/objtuple.rs index 0ed5bdf12..1042b3761 100644 --- a/vm/src/objtuple.rs +++ b/vm/src/objtuple.rs @@ -9,7 +9,7 @@ fn get_pos(l: &Vec, p: i32) -> usize { } } -pub fn get_item(rt: &mut VirtualMachine, l: &Vec, b: PyObjectRef) -> PyResult { +pub fn get_item(vm: &mut VirtualMachine, l: &Vec, b: PyObjectRef) -> PyResult { match &(b.borrow()).kind { PyObjectKind::Integer { value } => { let pos_index = get_pos(l, *value); @@ -17,7 +17,7 @@ pub fn get_item(rt: &mut VirtualMachine, l: &Vec, b: PyObjectRef) - let obj = l[pos_index].clone(); Ok(obj) } else { - Err(rt.new_exception("Index out of bounds!".to_string())) + Err(vm.new_exception("Index out of bounds!".to_string())) } } PyObjectKind::Slice { start, stop, step } => { @@ -39,11 +39,11 @@ pub fn get_item(rt: &mut VirtualMachine, l: &Vec, b: PyObjectRef) - PyObjectKind::Tuple { elements: l[start..stop].to_vec(), }, - rt.get_type(), + vm.get_type(), ); Ok(obj) } - _ => Err(rt.new_exception(format!( + _ => Err(vm.new_exception(format!( "TypeError: indexing type {:?} with index {:?} is not supported (yet?)", l, b ))), diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 39c680f1d..d509ca170 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -222,7 +222,13 @@ impl fmt::Debug for PyObject { } } -type RustPyFunc = fn(rt: &mut VirtualMachine, Vec) -> PyResult; +#[derive(Debug)] +pub struct PyFuncArgs { + pub args: Vec, + // TODO: add kwargs here +} + +type RustPyFunc = fn(vm: &mut VirtualMachine, PyFuncArgs) -> PyResult; pub enum PyObjectKind { String { @@ -316,9 +322,9 @@ impl PyObject { }.into_ref() } - pub fn call(&self, rt: &mut VirtualMachine, args: Vec) -> PyResult { + pub fn call(&self, vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { match self.kind { - PyObjectKind::RustFunction { ref function } => function(rt, args), + PyObjectKind::RustFunction { ref function } => function(vm, args), _ => { println!("Not impl {:?}", self); panic!("Not impl"); diff --git a/vm/src/vm.rs b/vm/src/vm.rs index b9d83eb14..e3045e3b1 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -16,7 +16,7 @@ use super::objlist; use super::objstr; use super::objtuple; use super::pyobject::{DictProtocol, PyContext, PyObject, PyObjectKind, PyObjectRef, - PyResult, ParentProtocol, Scope, IdProtocol}; + PyResult, ParentProtocol, Scope, IdProtocol, PyFuncArgs}; // use objects::objects; @@ -30,7 +30,10 @@ pub struct VirtualMachine { impl VirtualMachine { fn call(&mut self, f: PyObjectRef) -> PyResult { - self.invoke(f, Vec::new()) + let args = PyFuncArgs { + args: Vec::new(), + }; + self.invoke(f, args) } pub fn run_code_obj(&mut self, code: PyObjectRef, scope: PyObjectRef) -> PyResult { @@ -452,13 +455,13 @@ impl VirtualMachine { } } - fn new_instance(&mut self, type_ref: PyObjectRef, args: Vec) -> PyResult { + fn new_instance(&mut self, type_ref: PyObjectRef, args: PyFuncArgs) -> PyResult { // more or less __new__ operator let obj = PyObject::new(PyObjectKind::None, type_ref.clone()); Ok(obj) } - fn invoke(&mut self, func_ref: PyObjectRef, args: Vec) -> PyResult { + fn invoke(&mut self, func_ref: PyObjectRef, args: PyFuncArgs) -> PyResult { let f = func_ref.borrow(); match f.kind { @@ -466,7 +469,7 @@ impl VirtualMachine { PyObjectKind::Function { ref code, ref scope } => { let mut scope = self.new_scope(Some(scope.clone())); let code_object = copy_code(code.clone()); - for (name, value) in code_object.arg_names.iter().zip(args) { + for (name, value) in code_object.arg_names.iter().zip(args.args) { scope.set_item(name, value); } let frame = Frame::new(code.clone(), scope); @@ -665,6 +668,10 @@ impl VirtualMachine { } bytecode::Instruction::CallFunction { count } => { let args: Vec = self.pop_multiple(*count); + // TODO: kwargs + let args = PyFuncArgs { + args: args + }; let func_ref = self.pop_value(); // Call function: