mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Move max function test cases to snippet dir. Implement key and default argument on max function.
This commit is contained in:
1 parent
4acea45f78
commit
99af466a88
13 files changed
+192
-42
No files matched your search
@@ -197,6 +197,9 @@ where
|
||||
// Skip backslash and newline
|
||||
self.shift();
|
||||
self.shift();
|
||||
// Idea: insert trailing newline here:
|
||||
// } else if self.chr0 != Some('\n') && self.chr1.is_none() {
|
||||
// self.chr1 = Some('\n');
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
File renamed without changes.
@@ -17,3 +17,7 @@ assert list(zip(['a', 'b', 'c'], range(3), [9, 8, 7, 99])) == [('a', 0, 9), ('b'
|
||||
|
||||
assert list(filter(lambda x: ((x % 2) == 0), [0, 1, 2])) == [0, 2]
|
||||
|
||||
assert 3 == eval('1+2')
|
||||
|
||||
code = compile('5+3', 'x.py', 'eval')
|
||||
assert eval(code) == 8
|
||||
+88
-16
@@ -132,6 +132,8 @@ fn builtin_compile(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
]
|
||||
);
|
||||
let source = objstr::get_value(source);
|
||||
// TODO: fix this newline bug:
|
||||
let source = format!("{}\n", source);
|
||||
|
||||
let mode = {
|
||||
let mode = objstr::get_value(mode);
|
||||
@@ -206,19 +208,36 @@ fn builtin_eval(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
args,
|
||||
required = [
|
||||
(source, None), // TODO: Use more specific type
|
||||
required = [(source, None)],
|
||||
optional = [
|
||||
(_globals, Some(vm.ctx.dict_type())),
|
||||
(locals, Some(vm.ctx.dict_type()))
|
||||
]
|
||||
);
|
||||
// TODO: handle optional global and locals
|
||||
|
||||
let code_obj = source; // if source.borrow().kind
|
||||
// Determine code object:
|
||||
let code_obj = if objtype::isinstance(source, &vm.ctx.code_type()) {
|
||||
source.clone()
|
||||
} else if objtype::isinstance(source, &vm.ctx.str_type()) {
|
||||
let mode = compile::Mode::Eval;
|
||||
let source = objstr::get_value(source);
|
||||
// TODO: fix this newline bug:
|
||||
let source = format!("{}\n", source);
|
||||
compile::compile(vm, &source, mode, None)?
|
||||
} else {
|
||||
return Err(vm.new_type_error("code argument must be str or code object".to_string()));
|
||||
};
|
||||
|
||||
let locals = if let Some(locals) = locals {
|
||||
locals.clone()
|
||||
} else {
|
||||
vm.new_dict()
|
||||
};
|
||||
|
||||
// TODO: handle optional globals
|
||||
// Construct new scope:
|
||||
let scope_inner = Scope {
|
||||
locals: locals.clone(),
|
||||
locals: locals,
|
||||
parent: None,
|
||||
};
|
||||
let scope = PyObject {
|
||||
@@ -235,26 +254,38 @@ fn builtin_exec(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
args,
|
||||
required = [
|
||||
(source, None),
|
||||
required = [(source, None)],
|
||||
optional = [
|
||||
(_globals, Some(vm.ctx.dict_type())),
|
||||
(locals, Some(vm.ctx.dict_type()))
|
||||
]
|
||||
);
|
||||
// TODO: handle optional global and locals
|
||||
|
||||
// Determine code object:
|
||||
let code_obj = if objtype::isinstance(source, &vm.ctx.str_type()) {
|
||||
let mode = compile::Mode::Exec;
|
||||
let source = objstr::get_value(source);
|
||||
// TODO: fix this newline bug:
|
||||
let source = format!("{}\n", source);
|
||||
compile::compile(vm, &source, mode, None)?
|
||||
} else {
|
||||
} else if objtype::isinstance(source, &vm.ctx.code_type()) {
|
||||
source.clone()
|
||||
} else {
|
||||
return Err(vm.new_type_error("source argument must be str or code object".to_string()));
|
||||
};
|
||||
|
||||
// handle optional global and locals
|
||||
let locals = if let Some(locals) = locals {
|
||||
locals.clone()
|
||||
} else {
|
||||
vm.new_dict()
|
||||
};
|
||||
|
||||
// TODO: use globals
|
||||
|
||||
// Construct new scope:
|
||||
let scope_inner = Scope {
|
||||
locals: locals.clone(),
|
||||
locals: locals,
|
||||
parent: None,
|
||||
};
|
||||
let scope = PyObject {
|
||||
@@ -416,15 +447,56 @@ fn builtin_map(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
fn builtin_max(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(x, None), (y, None)]);
|
||||
// arg_check!(vm, args, required = [(x, None), (y, None)]);
|
||||
|
||||
let order = vm.call_method(x, "__gt__", vec![y.clone()])?;
|
||||
|
||||
if objbool::get_value(&order) {
|
||||
Ok(x.clone())
|
||||
let candidates = if args.args.len() > 1 {
|
||||
args.args.clone()
|
||||
} else if args.args.len() == 1 {
|
||||
vm.extract_elements(&args.args[0])?
|
||||
} else {
|
||||
Ok(y.clone())
|
||||
// zero arguments means type error:
|
||||
return Err(vm.new_type_error("Expected 1 or more arguments".to_string()));
|
||||
};
|
||||
|
||||
if candidates.len() == 0 {
|
||||
let default = args.get_optional_kwarg("default");
|
||||
if default.is_none() {
|
||||
return Err(vm.new_value_error("max() arg is an empty sequence".to_string()));
|
||||
} else {
|
||||
return Ok(default.unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
let key_func = args.get_optional_kwarg("key");
|
||||
|
||||
// Start with first assumption:
|
||||
let mut candidates_iter = candidates.into_iter();
|
||||
let mut x = candidates_iter.next().unwrap();
|
||||
// TODO: this key function looks pretty duplicate. Maybe we can create
|
||||
// a local function?
|
||||
let mut x_key = if let Some(f) = &key_func {
|
||||
let args = PyFuncArgs::new(vec![x.clone()], vec![]);
|
||||
vm.invoke(f.clone(), args)?
|
||||
} else {
|
||||
x.clone()
|
||||
};
|
||||
|
||||
for y in candidates_iter {
|
||||
let y_key = if let Some(f) = &key_func {
|
||||
let args = PyFuncArgs::new(vec![y.clone()], vec![]);
|
||||
vm.invoke(f.clone(), args)?
|
||||
} else {
|
||||
y.clone()
|
||||
};
|
||||
let order = vm.call_method(&x_key, "__gt__", vec![y_key.clone()])?;
|
||||
|
||||
if !objbool::get_value(&order) {
|
||||
x = y.clone();
|
||||
x_key = y_key;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
// builtin_memoryview
|
||||
|
||||
@@ -11,6 +11,7 @@ use super::objtype;
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
let ref code_type = context.code_type;
|
||||
code_type.set_attr("__new__", context.new_rustfunc(code_new));
|
||||
code_type.set_attr("__repr__", context.new_rustfunc(code_repr));
|
||||
}
|
||||
|
||||
@@ -24,6 +25,11 @@ pub fn copy_code(code_obj: &PyObjectRef) -> bytecode::CodeObject {
|
||||
}
|
||||
}
|
||||
|
||||
fn code_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(_cls, None)]);
|
||||
Err(vm.new_type_error(format!("Cannot directly create code object")))
|
||||
}
|
||||
|
||||
fn code_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(o, Some(vm.ctx.code_type()))]);
|
||||
|
||||
|
||||
@@ -109,6 +109,27 @@ fn dict_delitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
}
|
||||
|
||||
/// When iterating over a dictionary, we iterate over the keys of it.
|
||||
fn dict_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(dict, Some(vm.ctx.dict_type()))]);
|
||||
|
||||
let keys = get_elements(dict)
|
||||
.keys()
|
||||
.map(|k| vm.ctx.new_str(k.to_string()))
|
||||
.collect();
|
||||
let key_list = vm.ctx.new_list(keys);
|
||||
|
||||
let iter_obj = PyObject::new(
|
||||
PyObjectKind::Iterator {
|
||||
position: 0,
|
||||
iterated_obj: key_list,
|
||||
},
|
||||
vm.ctx.iter_type(),
|
||||
);
|
||||
|
||||
Ok(iter_obj)
|
||||
}
|
||||
|
||||
fn dict_setitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
@@ -165,6 +186,7 @@ pub fn init(context: &PyContext) {
|
||||
dict_type.set_attr("__contains__", context.new_rustfunc(dict_contains));
|
||||
dict_type.set_attr("__delitem__", context.new_rustfunc(dict_delitem));
|
||||
dict_type.set_attr("__getitem__", context.new_rustfunc(dict_getitem));
|
||||
dict_type.set_attr("__iter__", context.new_rustfunc(dict_iter));
|
||||
dict_type.set_attr("__new__", context.new_rustfunc(dict_new));
|
||||
dict_type.set_attr("__repr__", context.new_rustfunc(dict_repr));
|
||||
dict_type.set_attr("__setitem__", context.new_rustfunc(dict_setitem));
|
||||
|
||||
@@ -10,9 +10,15 @@ use super::objtype;
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
let ref frame_type = context.frame_type;
|
||||
frame_type.set_attr("__new__", context.new_rustfunc(frame_new));
|
||||
frame_type.set_attr("__repr__", context.new_rustfunc(frame_repr));
|
||||
}
|
||||
|
||||
fn frame_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(_cls, None)]);
|
||||
Err(vm.new_type_error(format!("Cannot directly create frame object")))
|
||||
}
|
||||
|
||||
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 .. >");
|
||||
|
||||
+5
-26
@@ -3,8 +3,7 @@
|
||||
*/
|
||||
|
||||
use super::super::pyobject::{
|
||||
AttributeProtocol, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, PyResult,
|
||||
TypeProtocol,
|
||||
AttributeProtocol, PyContext, PyFuncArgs, PyObjectKind, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objbool;
|
||||
@@ -17,30 +16,10 @@ use super::objtype; // Required for arg_check! to use isinstance
|
||||
* function 'iter' is called.
|
||||
*/
|
||||
pub fn get_iter(vm: &mut VirtualMachine, iter_target: &PyObjectRef) -> PyResult {
|
||||
// Check what we are going to iterate over:
|
||||
let iterated_obj = if objtype::isinstance(iter_target, &vm.ctx.iter_type()) {
|
||||
// If object is already an iterator, return that one.
|
||||
return Ok(iter_target.clone());
|
||||
} else if objtype::isinstance(iter_target, &vm.ctx.list_type()) {
|
||||
iter_target.clone()
|
||||
// } else if hasattr(iter_target, "__iter__") {
|
||||
} else {
|
||||
return vm.call_method(iter_target, "__iter__", vec![]);
|
||||
// let type_str = objstr::get_value(&vm.to_str(iter_target.typ()).unwrap());
|
||||
// let type_error = vm.new_type_error(format!("Cannot iterate over {}", type_str));
|
||||
// return Err(type_error);
|
||||
};
|
||||
|
||||
let iter_obj = PyObject::new(
|
||||
PyObjectKind::Iterator {
|
||||
position: 0,
|
||||
iterated_obj: iterated_obj,
|
||||
},
|
||||
vm.ctx.iter_type(),
|
||||
);
|
||||
|
||||
// We are all good here:
|
||||
Ok(iter_obj)
|
||||
vm.call_method(iter_target, "__iter__", vec![])
|
||||
// let type_str = objstr::get_value(&vm.to_str(iter_target.typ()).unwrap());
|
||||
// let type_error = vm.new_type_error(format!("Cannot iterate over {}", type_str));
|
||||
// return Err(type_error);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -183,6 +183,21 @@ fn list_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
get_item(vm, list, &get_elements(list), needle.clone())
|
||||
}
|
||||
|
||||
fn list_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(list, Some(vm.ctx.list_type()))]);
|
||||
|
||||
let iter_obj = PyObject::new(
|
||||
PyObjectKind::Iterator {
|
||||
position: 0,
|
||||
iterated_obj: list.clone(),
|
||||
},
|
||||
vm.ctx.iter_type(),
|
||||
);
|
||||
|
||||
// We are all good here:
|
||||
Ok(iter_obj)
|
||||
}
|
||||
|
||||
fn list_setitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
@@ -199,6 +214,7 @@ pub fn init(context: &PyContext) {
|
||||
list_type.set_attr("__contains__", context.new_rustfunc(list_contains));
|
||||
list_type.set_attr("__eq__", context.new_rustfunc(list_eq));
|
||||
list_type.set_attr("__getitem__", context.new_rustfunc(list_getitem));
|
||||
list_type.set_attr("__iter__", context.new_rustfunc(list_iter));
|
||||
list_type.set_attr("__setitem__", context.new_rustfunc(list_setitem));
|
||||
list_type.set_attr("__len__", context.new_rustfunc(list_len));
|
||||
list_type.set_attr("__new__", context.new_rustfunc(list_new));
|
||||
|
||||
@@ -14,6 +14,7 @@ pub fn init(context: &PyContext) {
|
||||
str_type.set_attr("__eq__", context.new_rustfunc(str_eq));
|
||||
str_type.set_attr("__contains__", context.new_rustfunc(str_contains));
|
||||
str_type.set_attr("__getitem__", context.new_rustfunc(str_getitem));
|
||||
str_type.set_attr("__gt__", context.new_rustfunc(str_gt));
|
||||
str_type.set_attr("__len__", context.new_rustfunc(str_len));
|
||||
str_type.set_attr("__mul__", context.new_rustfunc(str_mul));
|
||||
str_type.set_attr("__new__", context.new_rustfunc(str_new));
|
||||
@@ -53,6 +54,21 @@ fn str_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
Ok(vm.ctx.new_bool(result))
|
||||
}
|
||||
|
||||
fn str_gt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
args,
|
||||
required = [
|
||||
(zelf, Some(vm.ctx.str_type())),
|
||||
(other, Some(vm.ctx.str_type()))
|
||||
]
|
||||
);
|
||||
let zelf = get_value(zelf);
|
||||
let other = get_value(other);
|
||||
let result = zelf > other;
|
||||
Ok(vm.ctx.new_bool(result))
|
||||
}
|
||||
|
||||
fn str_str(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(s, Some(vm.ctx.str_type()))]);
|
||||
Ok(s.clone())
|
||||
|
||||
@@ -48,6 +48,20 @@ fn tuple_hash(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
Ok(vm.ctx.new_int(x.to_bigint().unwrap()))
|
||||
}
|
||||
|
||||
fn tuple_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(tuple, Some(vm.ctx.tuple_type()))]);
|
||||
|
||||
let iter_obj = PyObject::new(
|
||||
PyObjectKind::Iterator {
|
||||
position: 0,
|
||||
iterated_obj: tuple.clone(),
|
||||
},
|
||||
vm.ctx.iter_type(),
|
||||
);
|
||||
|
||||
Ok(iter_obj)
|
||||
}
|
||||
|
||||
fn tuple_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(zelf, Some(vm.ctx.tuple_type()))]);
|
||||
let elements = get_elements(zelf);
|
||||
@@ -132,6 +146,7 @@ pub fn init(context: &PyContext) {
|
||||
tuple_type.set_attr("__contains__", context.new_rustfunc(tuple_contains));
|
||||
tuple_type.set_attr("__getitem__", context.new_rustfunc(tuple_getitem));
|
||||
tuple_type.set_attr("__hash__", context.new_rustfunc(tuple_hash));
|
||||
tuple_type.set_attr("__iter__", context.new_rustfunc(tuple_iter));
|
||||
tuple_type.set_attr("__len__", context.new_rustfunc(tuple_len));
|
||||
tuple_type.set_attr("__new__", context.new_rustfunc(tuple_new));
|
||||
tuple_type.set_attr("__repr__", context.new_rustfunc(tuple_repr));
|
||||
|
||||
@@ -728,6 +728,15 @@ impl PyFuncArgs {
|
||||
}
|
||||
default.clone()
|
||||
}
|
||||
|
||||
pub fn get_optional_kwarg(&self, key: &str) -> Option<PyObjectRef> {
|
||||
for (arg_name, arg_value) in self.kwargs.iter() {
|
||||
if arg_name == key {
|
||||
return Some(arg_value.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
type RustPyFunc = fn(vm: &mut VirtualMachine, PyFuncArgs) -> PyResult;
|
||||
|
||||
@@ -35,6 +35,7 @@ pub struct VirtualMachine {
|
||||
pub sys_module: PyObjectRef,
|
||||
pub stdlib_inits: HashMap<String, stdlib::StdlibInitFunc>,
|
||||
pub ctx: PyContext,
|
||||
pub current_frame: Option<PyObjectRef>,
|
||||
}
|
||||
|
||||
impl VirtualMachine {
|
||||
@@ -51,6 +52,7 @@ impl VirtualMachine {
|
||||
sys_module: sysmod,
|
||||
stdlib_inits,
|
||||
ctx: ctx,
|
||||
current_frame: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user