Change rt to vm and change args into an object holding both args and kwargs

This commit is contained in:
Windel Bouwman
2018-08-02 17:28:33 +02:00
parent f7aa1dd822
commit eb2cc5b055
9 changed files with 87 additions and 73 deletions

View File

@@ -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<PyObjectRef>) -> 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<PyObjectRef>) -> 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<PyObjectRef>) -> 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<PyObjectRef>) -> 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<PyObjectRef>) -> 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<PyObjectRef>) -> 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<PyObjectRef>) -> 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<PyObjectRef>) -> 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<PyObjectRef>) -> 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<PyObjectRef>) -> 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))))
}

View File

@@ -14,7 +14,7 @@ struct Compiler {
nxt_label: usize,
}
pub fn compile(rt: &mut VirtualMachine, source: &String, mode: Mode) -> Result<PyObjectRef, String> {
pub fn compile(vm: &mut VirtualMachine, source: &String, mode: Mode) -> Result<PyObjectRef, String> {
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<P
let code = compiler.pop_code_object();
Ok(PyObject::new(
PyObjectKind::Code { code: code },
rt.get_type(),
vm.get_type(),
))
}

View File

@@ -1,8 +1,8 @@
use super::pyobject::{PyObjectRef, PyResult};
use super::vm::VirtualMachine;
pub fn set_item(rt: &mut VirtualMachine, d: PyObjectRef, idx: PyObjectRef, obj: PyObjectRef) -> PyResult {
Ok(rt.get_none())
pub fn set_item(vm: &mut VirtualMachine, d: PyObjectRef, idx: PyObjectRef, obj: PyObjectRef) -> PyResult {
Ok(vm.get_none())
}
/* TODO:

View File

@@ -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<PyObjectRef>) -> Result<PyObjectRef, PyObjectRef> {
Ok(rt.new_str("todo".to_string()))
fn str(vm: &mut VirtualMachine, args: PyFuncArgs) -> Result<PyObjectRef, PyObjectRef> {
Ok(vm.new_str("todo".to_string()))
}
fn add() {}

View File

@@ -9,7 +9,7 @@ fn get_pos(l: &Vec<PyObjectRef>, p: i32) -> usize {
}
}
pub fn get_item(rt: &mut VirtualMachine, l: &Vec<PyObjectRef>, b: PyObjectRef) -> PyResult {
pub fn get_item(vm: &mut VirtualMachine, l: &Vec<PyObjectRef>, 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<PyObjectRef>, 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<PyObjectRef>, 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<PyObjectRef>, b: PyObjectRef) -
// set_item:
pub fn set_item(
rt: &mut VirtualMachine,
vm: &mut VirtualMachine,
l: &mut Vec<PyObjectRef>,
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:

View File

@@ -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?)",

View File

@@ -9,7 +9,7 @@ fn get_pos(l: &Vec<PyObjectRef>, p: i32) -> usize {
}
}
pub fn get_item(rt: &mut VirtualMachine, l: &Vec<PyObjectRef>, b: PyObjectRef) -> PyResult {
pub fn get_item(vm: &mut VirtualMachine, l: &Vec<PyObjectRef>, 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<PyObjectRef>, 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<PyObjectRef>, 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
))),

View File

@@ -222,7 +222,13 @@ impl fmt::Debug for PyObject {
}
}
type RustPyFunc = fn(rt: &mut VirtualMachine, Vec<PyObjectRef>) -> PyResult;
#[derive(Debug)]
pub struct PyFuncArgs {
pub args: Vec<PyObjectRef>,
// 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<PyObjectRef>) -> 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");

View File

@@ -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<PyObjectRef>) -> 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<PyObjectRef>) -> 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<PyObjectRef> = self.pop_multiple(*count);
// TODO: kwargs
let args = PyFuncArgs {
args: args
};
let func_ref = self.pop_value();
// Call function: