mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-09 22:49:57 +09:00
Merge branch 'master' into master
This commit is contained in:
@@ -27,6 +27,7 @@ assert len(range(5, 10, 2)) == 3, 'Expected length 3, for elements: 5, 7, 9'
|
||||
assert range(10).index(6) == 6
|
||||
assert range(4, 10).index(6) == 2
|
||||
assert range(4, 10, 2).index(6) == 1
|
||||
assert range(10, 4, -2).index(8) == 1
|
||||
|
||||
# index raises value error on out of bounds
|
||||
assert_raises(lambda _: range(10).index(-1), ValueError)
|
||||
@@ -34,3 +35,25 @@ assert_raises(lambda _: range(10).index(10), ValueError)
|
||||
|
||||
# index raises value error if out of step
|
||||
assert_raises(lambda _: range(4, 10, 2).index(5), ValueError)
|
||||
|
||||
# index raises value error if needle is not an int
|
||||
assert_raises(lambda _: range(10).index('foo'), ValueError)
|
||||
|
||||
# __bool__
|
||||
assert range(1).__bool__()
|
||||
assert range(1, 2).__bool__()
|
||||
|
||||
assert not range(0).__bool__()
|
||||
assert not range(1, 1).__bool__()
|
||||
|
||||
# __contains__
|
||||
assert range(10).__contains__(6)
|
||||
assert range(4, 10).__contains__(6)
|
||||
assert range(4, 10, 2).__contains__(6)
|
||||
assert range(10, 4, -2).__contains__(10)
|
||||
assert range(10, 4, -2).__contains__(8)
|
||||
|
||||
assert not range(10).__contains__(-1)
|
||||
assert not range(10, 4, -2).__contains__(9)
|
||||
assert not range(10, 4, -2).__contains__(4)
|
||||
assert not range(10).__contains__('foo')
|
||||
|
||||
@@ -19,3 +19,5 @@ assert x > y, "tuple __gt__ failed"
|
||||
|
||||
b = (1,2,3)
|
||||
assert b.index(2) == 1
|
||||
|
||||
assert b.__doc__ == "tuple() -> empty tuple\ntuple(iterable) -> tuple initialized from iterable's items\n\nIf the argument is a tuple, the return value is the same object."
|
||||
|
||||
@@ -136,11 +136,11 @@ fn builtin_compile(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
let mode = {
|
||||
let mode = objstr::get_value(mode);
|
||||
if mode == String::from("exec") {
|
||||
if mode == "exec" {
|
||||
compile::Mode::Exec
|
||||
} else if mode == "eval".to_string() {
|
||||
} else if mode == "eval" {
|
||||
compile::Mode::Eval
|
||||
} else if mode == "single".to_string() {
|
||||
} else if mode == "single" {
|
||||
compile::Mode::Single
|
||||
} else {
|
||||
return Err(
|
||||
|
||||
@@ -45,9 +45,8 @@ pub fn compile(
|
||||
},
|
||||
};
|
||||
|
||||
match result {
|
||||
Err(msg) => return Err(vm.new_exception(syntax_error.clone(), msg)),
|
||||
_ => {}
|
||||
if let Err(msg) = result {
|
||||
return Err(vm.new_exception(syntax_error.clone(), msg));
|
||||
}
|
||||
|
||||
let code = compiler.pop_code_object();
|
||||
@@ -589,7 +588,7 @@ impl Compiler {
|
||||
ast::Statement::Assign { targets, value } => {
|
||||
self.compile_expression(value)?;
|
||||
|
||||
for (i, target) in targets.into_iter().enumerate() {
|
||||
for (i, target) in targets.iter().enumerate() {
|
||||
if i + 1 != targets.len() {
|
||||
self.emit(Instruction::Duplicate);
|
||||
}
|
||||
@@ -665,7 +664,7 @@ impl Compiler {
|
||||
|
||||
let mut flags = bytecode::FunctionOpArg::empty();
|
||||
if have_kwargs {
|
||||
flags = flags | bytecode::FunctionOpArg::HAS_DEFAULTS;
|
||||
flags |= bytecode::FunctionOpArg::HAS_DEFAULTS;
|
||||
}
|
||||
|
||||
Ok(flags)
|
||||
|
||||
@@ -314,7 +314,7 @@ impl FormatSpec {
|
||||
}
|
||||
None => Ok(magnitude.to_str_radix(10)),
|
||||
};
|
||||
if !raw_magnitude_string_result.is_ok() {
|
||||
if raw_magnitude_string_result.is_err() {
|
||||
return raw_magnitude_string_result;
|
||||
}
|
||||
let magnitude_string = format!(
|
||||
|
||||
@@ -610,7 +610,7 @@ impl Frame {
|
||||
.iter()
|
||||
.skip(*before)
|
||||
.take(middle)
|
||||
.map(|x| x.clone())
|
||||
.cloned()
|
||||
.collect();
|
||||
let t = vm.ctx.new_list(middle_elements);
|
||||
self.push_value(t);
|
||||
@@ -886,25 +886,25 @@ impl Frame {
|
||||
) -> FrameResult {
|
||||
let b_ref = self.pop_value();
|
||||
let a_ref = self.pop_value();
|
||||
let value = match op {
|
||||
&bytecode::BinaryOperator::Subtract => vm._sub(a_ref, b_ref),
|
||||
&bytecode::BinaryOperator::Add => vm._add(a_ref, b_ref),
|
||||
&bytecode::BinaryOperator::Multiply => vm._mul(a_ref, b_ref),
|
||||
&bytecode::BinaryOperator::MatrixMultiply => {
|
||||
let value = match *op {
|
||||
bytecode::BinaryOperator::Subtract => vm._sub(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Add => vm._add(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Multiply => vm._mul(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::MatrixMultiply => {
|
||||
vm.call_method(&a_ref, "__matmul__", vec![b_ref])
|
||||
}
|
||||
&bytecode::BinaryOperator::Power => vm._pow(a_ref, b_ref),
|
||||
&bytecode::BinaryOperator::Divide => vm._div(a_ref, b_ref),
|
||||
&bytecode::BinaryOperator::FloorDivide => {
|
||||
bytecode::BinaryOperator::Power => vm._pow(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Divide => vm._div(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::FloorDivide => {
|
||||
vm.call_method(&a_ref, "__floordiv__", vec![b_ref])
|
||||
}
|
||||
&bytecode::BinaryOperator::Subscript => self.subscript(vm, a_ref, b_ref),
|
||||
&bytecode::BinaryOperator::Modulo => vm._modulo(a_ref, b_ref),
|
||||
&bytecode::BinaryOperator::Lshift => vm.call_method(&a_ref, "__lshift__", vec![b_ref]),
|
||||
&bytecode::BinaryOperator::Rshift => vm.call_method(&a_ref, "__rshift__", vec![b_ref]),
|
||||
&bytecode::BinaryOperator::Xor => vm._xor(a_ref, b_ref),
|
||||
&bytecode::BinaryOperator::Or => vm._or(a_ref, b_ref),
|
||||
&bytecode::BinaryOperator::And => vm._and(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Subscript => self.subscript(vm, a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Modulo => vm._modulo(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Lshift => vm.call_method(&a_ref, "__lshift__", vec![b_ref]),
|
||||
bytecode::BinaryOperator::Rshift => vm.call_method(&a_ref, "__rshift__", vec![b_ref]),
|
||||
bytecode::BinaryOperator::Xor => vm._xor(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Or => vm._or(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::And => vm._and(a_ref, b_ref),
|
||||
}?;
|
||||
|
||||
self.push_value(value);
|
||||
@@ -917,11 +917,11 @@ impl Frame {
|
||||
op: &bytecode::UnaryOperator,
|
||||
) -> FrameResult {
|
||||
let a = self.pop_value();
|
||||
let value = match op {
|
||||
&bytecode::UnaryOperator::Minus => vm.call_method(&a, "__neg__", vec![])?,
|
||||
&bytecode::UnaryOperator::Plus => vm.call_method(&a, "__pos__", vec![])?,
|
||||
&bytecode::UnaryOperator::Invert => vm.call_method(&a, "__invert__", vec![])?,
|
||||
&bytecode::UnaryOperator::Not => {
|
||||
let value = match *op {
|
||||
bytecode::UnaryOperator::Minus => vm.call_method(&a, "__neg__", vec![])?,
|
||||
bytecode::UnaryOperator::Plus => vm.call_method(&a, "__pos__", vec![])?,
|
||||
bytecode::UnaryOperator::Invert => vm.call_method(&a, "__invert__", vec![])?,
|
||||
bytecode::UnaryOperator::Not => {
|
||||
let value = objbool::boolval(vm, a)?;
|
||||
vm.ctx.new_bool(!value)
|
||||
}
|
||||
@@ -994,17 +994,17 @@ impl Frame {
|
||||
) -> FrameResult {
|
||||
let b = self.pop_value();
|
||||
let a = self.pop_value();
|
||||
let value = match op {
|
||||
&bytecode::ComparisonOperator::Equal => vm._eq(&a, b)?,
|
||||
&bytecode::ComparisonOperator::NotEqual => vm._ne(&a, b)?,
|
||||
&bytecode::ComparisonOperator::Less => vm._lt(&a, b)?,
|
||||
&bytecode::ComparisonOperator::LessOrEqual => vm._le(&a, b)?,
|
||||
&bytecode::ComparisonOperator::Greater => vm._gt(&a, b)?,
|
||||
&bytecode::ComparisonOperator::GreaterOrEqual => vm._ge(&a, b)?,
|
||||
&bytecode::ComparisonOperator::Is => vm.ctx.new_bool(self._is(a, b)),
|
||||
&bytecode::ComparisonOperator::IsNot => self._is_not(vm, a, b)?,
|
||||
&bytecode::ComparisonOperator::In => self._in(vm, a, b)?,
|
||||
&bytecode::ComparisonOperator::NotIn => self._not_in(vm, a, b)?,
|
||||
let value = match *op {
|
||||
bytecode::ComparisonOperator::Equal => vm._eq(&a, b)?,
|
||||
bytecode::ComparisonOperator::NotEqual => vm._ne(&a, b)?,
|
||||
bytecode::ComparisonOperator::Less => vm._lt(&a, b)?,
|
||||
bytecode::ComparisonOperator::LessOrEqual => vm._le(&a, b)?,
|
||||
bytecode::ComparisonOperator::Greater => vm._gt(&a, b)?,
|
||||
bytecode::ComparisonOperator::GreaterOrEqual => vm._ge(&a, b)?,
|
||||
bytecode::ComparisonOperator::Is => vm.ctx.new_bool(self._is(a, b)),
|
||||
bytecode::ComparisonOperator::IsNot => self._is_not(vm, a, b)?,
|
||||
bytecode::ComparisonOperator::In => self._in(vm, a, b)?,
|
||||
bytecode::ComparisonOperator::NotIn => self._not_in(vm, a, b)?,
|
||||
};
|
||||
|
||||
self.push_value(value);
|
||||
|
||||
@@ -103,7 +103,7 @@ fn find_source(vm: &VirtualMachine, current_path: PathBuf, name: &str) -> Result
|
||||
}
|
||||
}
|
||||
|
||||
match filepaths.iter().filter(|p| p.exists()).next() {
|
||||
match filepaths.iter().find(|p| p.exists()) {
|
||||
Some(path) => Ok(path.to_path_buf()),
|
||||
None => Err(format!("No module named '{}'", name)),
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> Result<bool, PyObje
|
||||
PyObjectPayload::Integer { ref value } => !value.is_zero(),
|
||||
_ => return Err(vm.new_type_error(String::from("TypeError"))),
|
||||
};
|
||||
|
||||
v
|
||||
} else {
|
||||
true
|
||||
@@ -81,7 +82,7 @@ fn bool_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
Ok(match val {
|
||||
Some(val) => {
|
||||
let bv = boolval(vm, val.clone())?;
|
||||
vm.new_bool(bv.clone())
|
||||
vm.new_bool(bv)
|
||||
}
|
||||
None => vm.context().new_bool(false),
|
||||
})
|
||||
|
||||
@@ -14,12 +14,29 @@ use std::ops::Deref;
|
||||
// Fill bytes class methods:
|
||||
pub fn init(context: &PyContext) {
|
||||
let bytes_type = &context.bytes_type;
|
||||
|
||||
let bytes_doc =
|
||||
"bytes(iterable_of_ints) -> bytes\n\
|
||||
bytes(string, encoding[, errors]) -> bytes\n\
|
||||
bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer\n\
|
||||
bytes(int) -> bytes object of size given by the parameter initialized with null bytes\n\
|
||||
bytes() -> empty bytes object\n\nConstruct an immutable array of bytes from:\n \
|
||||
- an iterable yielding integers in range(256)\n \
|
||||
- a text string encoded using the specified encoding\n \
|
||||
- any object implementing the buffer API.\n \
|
||||
- an integer";
|
||||
|
||||
context.set_attr(bytes_type, "__eq__", context.new_rustfunc(bytes_eq));
|
||||
context.set_attr(bytes_type, "__hash__", context.new_rustfunc(bytes_hash));
|
||||
context.set_attr(bytes_type, "__new__", context.new_rustfunc(bytes_new));
|
||||
context.set_attr(bytes_type, "__repr__", context.new_rustfunc(bytes_repr));
|
||||
context.set_attr(bytes_type, "__len__", context.new_rustfunc(bytes_len));
|
||||
context.set_attr(bytes_type, "__iter__", context.new_rustfunc(bytes_iter))
|
||||
context.set_attr(bytes_type, "__iter__", context.new_rustfunc(bytes_iter));
|
||||
context.set_attr(
|
||||
bytes_type,
|
||||
"__doc__",
|
||||
context.new_str(bytes_doc.to_string()),
|
||||
);
|
||||
}
|
||||
|
||||
fn bytes_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
@@ -5,7 +5,7 @@ use super::super::vm::VirtualMachine;
|
||||
use super::objiter;
|
||||
use super::objstr;
|
||||
use super::objtype;
|
||||
use std::cell::{Ref, RefMut};
|
||||
use std::cell::{Ref, RefCell, RefMut};
|
||||
use std::collections::HashMap;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
@@ -105,10 +105,7 @@ pub fn contains_key_str(dict: &PyObjectRef, key: &str) -> bool {
|
||||
|
||||
pub fn content_contains_key_str(elements: &DictContentType, key: &str) -> bool {
|
||||
// TODO: let hash: usize = key;
|
||||
match elements.get(key) {
|
||||
Some(_) => true,
|
||||
None => false,
|
||||
}
|
||||
elements.get(key).is_some()
|
||||
}
|
||||
|
||||
// Python dict methods:
|
||||
@@ -139,7 +136,7 @@ fn dict_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let elem_iter = objiter::get_iter(vm, &element)?;
|
||||
let needle = objiter::get_next_object(vm, &elem_iter)?.ok_or_else(|| err(vm))?;
|
||||
let value = objiter::get_next_object(vm, &elem_iter)?.ok_or_else(|| err(vm))?;
|
||||
if let Some(_) = objiter::get_next_object(vm, &elem_iter)? {
|
||||
if objiter::get_next_object(vm, &elem_iter)?.is_some() {
|
||||
return Err(err(vm));
|
||||
}
|
||||
set_item(&dict, &needle, &value);
|
||||
@@ -276,7 +273,7 @@ fn dict_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, dict_type: PyObjectRef) {
|
||||
(*dict_type.borrow_mut()).payload = PyObjectPayload::Class {
|
||||
name: String::from("dict"),
|
||||
dict: new(dict_type.clone()),
|
||||
dict: RefCell::new(HashMap::new()),
|
||||
mro: vec![object_type],
|
||||
};
|
||||
(*dict_type.borrow_mut()).typ = Some(type_type.clone());
|
||||
|
||||
@@ -268,6 +268,9 @@ fn float_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
let float_type = &context.float_type;
|
||||
|
||||
let float_doc = "Convert a string or number to a floating point number, if possible.";
|
||||
|
||||
context.set_attr(&float_type, "__eq__", context.new_rustfunc(float_eq));
|
||||
context.set_attr(&float_type, "__lt__", context.new_rustfunc(float_lt));
|
||||
context.set_attr(&float_type, "__le__", context.new_rustfunc(float_le));
|
||||
@@ -291,4 +294,9 @@ pub fn init(context: &PyContext) {
|
||||
context.set_attr(&float_type, "__pow__", context.new_rustfunc(float_pow));
|
||||
context.set_attr(&float_type, "__sub__", context.new_rustfunc(float_sub));
|
||||
context.set_attr(&float_type, "__repr__", context.new_rustfunc(float_repr));
|
||||
context.set_attr(
|
||||
&float_type,
|
||||
"__doc__",
|
||||
context.new_str(float_doc.to_string()),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::super::pyobject::{
|
||||
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef,
|
||||
PyResult, TypeProtocol,
|
||||
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult,
|
||||
TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objtype;
|
||||
@@ -110,12 +110,7 @@ fn classmethod_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
trace!("classmethod.__new__ {:?}", args.args);
|
||||
arg_check!(vm, args, required = [(cls, None), (callable, None)]);
|
||||
|
||||
let py_obj = PyObject::new(
|
||||
PyObjectPayload::Instance {
|
||||
dict: vm.ctx.new_dict(),
|
||||
},
|
||||
cls.clone(),
|
||||
);
|
||||
let py_obj = vm.ctx.new_instance(cls.clone(), None);
|
||||
vm.ctx.set_attr(&py_obj, "function", callable.clone());
|
||||
Ok(py_obj)
|
||||
}
|
||||
@@ -148,12 +143,7 @@ fn staticmethod_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
trace!("staticmethod.__new__ {:?}", args.args);
|
||||
arg_check!(vm, args, required = [(cls, None), (callable, None)]);
|
||||
|
||||
let py_obj = PyObject::new(
|
||||
PyObjectPayload::Instance {
|
||||
dict: vm.ctx.new_dict(),
|
||||
},
|
||||
cls.clone(),
|
||||
);
|
||||
let py_obj = vm.ctx.new_instance(cls.clone(), None);
|
||||
vm.ctx.set_attr(&py_obj, "function", callable.clone());
|
||||
Ok(py_obj)
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ fn list_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
if objtype::isinstance(o2, &vm.ctx.list_type()) {
|
||||
let e1 = get_elements(o);
|
||||
let e2 = get_elements(o2);
|
||||
let elements = e1.iter().chain(e2.iter()).map(|e| e.clone()).collect();
|
||||
let elements = e1.iter().chain(e2.iter()).cloned().collect();
|
||||
Ok(vm.ctx.new_list(elements))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!("Cannot add {} and {}", o.borrow(), o2.borrow())))
|
||||
@@ -223,7 +223,7 @@ fn list_count(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
for element in elements.iter() {
|
||||
let is_eq = vm._eq(element, value.clone())?;
|
||||
if objbool::boolval(vm, is_eq)? {
|
||||
count = count + 1;
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
Ok(vm.context().new_int(count))
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
use super::super::pyobject::{
|
||||
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef,
|
||||
PyResult, TypeProtocol,
|
||||
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult,
|
||||
TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objbool;
|
||||
use super::objdict;
|
||||
use super::objstr;
|
||||
use super::objtype;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub fn new_instance(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
|
||||
// more or less __new__ operator
|
||||
let type_ref = args.shift();
|
||||
let dict = vm.new_dict();
|
||||
let obj = PyObject::new(PyObjectPayload::Instance { dict }, type_ref.clone());
|
||||
let obj = vm.ctx.new_instance(type_ref.clone(), None);
|
||||
Ok(obj)
|
||||
}
|
||||
|
||||
pub fn create_object(type_type: PyObjectRef, object_type: PyObjectRef, dict_type: PyObjectRef) {
|
||||
pub fn create_object(type_type: PyObjectRef, object_type: PyObjectRef, _dict_type: PyObjectRef) {
|
||||
(*object_type.borrow_mut()).payload = PyObjectPayload::Class {
|
||||
name: String::from("object"),
|
||||
dict: objdict::new(dict_type),
|
||||
dict: RefCell::new(HashMap::new()),
|
||||
mro: vec![],
|
||||
};
|
||||
(*object_type.borrow_mut()).typ = Some(type_type.clone());
|
||||
@@ -62,15 +62,14 @@ fn object_delattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
]
|
||||
);
|
||||
|
||||
// Get dict:
|
||||
let dict = match zelf.borrow().payload {
|
||||
PyObjectPayload::Class { ref dict, .. } => dict.clone(),
|
||||
PyObjectPayload::Instance { ref dict, .. } => dict.clone(),
|
||||
_ => return Err(vm.new_type_error("TypeError: no dictionary.".to_string())),
|
||||
};
|
||||
|
||||
// Delete attr from dict:
|
||||
vm.call_method(&dict, "__delitem__", vec![attr.clone()])
|
||||
match zelf.borrow().payload {
|
||||
PyObjectPayload::Class { ref dict, .. } | PyObjectPayload::Instance { ref dict, .. } => {
|
||||
let attr_name = objstr::get_value(attr);
|
||||
dict.borrow_mut().remove(&attr_name);
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
_ => Err(vm.new_type_error("TypeError: no dictionary.".to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
fn object_str(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
@@ -116,8 +115,13 @@ fn object_init(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult {
|
||||
|
||||
fn object_dict(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
match args.args[0].borrow().payload {
|
||||
PyObjectPayload::Class { ref dict, .. } => Ok(dict.clone()),
|
||||
PyObjectPayload::Instance { ref dict, .. } => Ok(dict.clone()),
|
||||
PyObjectPayload::Class { ref dict, .. } | PyObjectPayload::Instance { ref dict, .. } => {
|
||||
let new_dict = vm.new_dict();
|
||||
for (attr, value) in dict.borrow().iter() {
|
||||
vm.ctx.set_item(&new_dict, &attr, value.clone());
|
||||
}
|
||||
Ok(new_dict)
|
||||
}
|
||||
_ => Err(vm.new_type_error("TypeError: no dictionary.".to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
*/
|
||||
|
||||
use super::super::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objtype;
|
||||
|
||||
@@ -55,12 +53,7 @@ fn property_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
trace!("property.__new__ {:?}", args.args);
|
||||
arg_check!(vm, args, required = [(cls, None), (fget, None)]);
|
||||
|
||||
let py_obj = PyObject::new(
|
||||
PyObjectPayload::Instance {
|
||||
dict: vm.ctx.new_dict(),
|
||||
},
|
||||
cls.clone(),
|
||||
);
|
||||
let py_obj = vm.ctx.new_instance(cls.clone(), None);
|
||||
vm.ctx.set_attr(&py_obj, "fget", fget.clone());
|
||||
Ok(py_obj)
|
||||
}
|
||||
|
||||
@@ -39,16 +39,29 @@ impl RangeType {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn index_of(&self, value: &BigInt) -> Option<BigInt> {
|
||||
if value < &self.start || value >= &self.end {
|
||||
return None;
|
||||
fn offset(&self, value: &BigInt) -> Option<BigInt> {
|
||||
match self.step.sign() {
|
||||
Sign::Plus if value >= &self.start && value < &self.end => Some(value - &self.start),
|
||||
Sign::Minus if value <= &self.start && value > &self.end => Some(&self.start - value),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
let offset = value - &self.start;
|
||||
if offset.is_multiple_of(&self.step) {
|
||||
Some(offset / &self.step)
|
||||
} else {
|
||||
None
|
||||
#[inline]
|
||||
pub fn contains(&self, value: &BigInt) -> bool {
|
||||
match self.offset(value) {
|
||||
Some(ref offset) => offset.is_multiple_of(&self.step),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn index_of(&self, value: &BigInt) -> Option<BigInt> {
|
||||
match self.offset(value) {
|
||||
Some(ref offset) if offset.is_multiple_of(&self.step) => {
|
||||
Some((offset / &self.step).abs())
|
||||
}
|
||||
Some(_) | None => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +110,12 @@ pub fn init(context: &PyContext) {
|
||||
context.new_rustfunc(range_getitem),
|
||||
);
|
||||
context.set_attr(&range_type, "__repr__", context.new_rustfunc(range_repr));
|
||||
context.set_attr(&range_type, "__bool__", context.new_rustfunc(range_bool));
|
||||
context.set_attr(
|
||||
&range_type,
|
||||
"__contains__",
|
||||
context.new_rustfunc(range_contains),
|
||||
);
|
||||
context.set_attr(&range_type, "index", context.new_rustfunc(range_index));
|
||||
}
|
||||
|
||||
@@ -240,6 +259,34 @@ fn range_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
Ok(vm.ctx.new_str(s))
|
||||
}
|
||||
|
||||
fn range_bool(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(zelf, Some(vm.ctx.range_type()))]);
|
||||
|
||||
let len = match zelf.borrow().payload {
|
||||
PyObjectPayload::Range { ref range } => range.len(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
Ok(vm.ctx.new_bool(len > 0))
|
||||
}
|
||||
|
||||
fn range_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
args,
|
||||
required = [(zelf, Some(vm.ctx.range_type())), (needle, None)]
|
||||
);
|
||||
|
||||
if let PyObjectPayload::Range { ref range } = zelf.borrow().payload {
|
||||
Ok(vm.ctx.new_bool(match needle.borrow().payload {
|
||||
PyObjectPayload::Integer { ref value } => range.contains(value),
|
||||
_ => false,
|
||||
}))
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
fn range_index(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
|
||||
@@ -34,17 +34,17 @@ pub trait PySliceableSequence {
|
||||
// TODO: we could potentially avoid this copy and use slice
|
||||
match &(slice.borrow()).payload {
|
||||
PyObjectPayload::Slice { start, stop, step } => {
|
||||
let start = match start {
|
||||
&Some(start) => self.get_pos(start),
|
||||
&None => 0,
|
||||
let start = match *start {
|
||||
Some(start) => self.get_pos(start),
|
||||
None => 0,
|
||||
};
|
||||
let stop = match stop {
|
||||
&Some(stop) => self.get_pos(stop),
|
||||
&None => self.len() as usize,
|
||||
let stop = match *stop {
|
||||
Some(stop) => self.get_pos(stop),
|
||||
None => self.len() as usize,
|
||||
};
|
||||
match step {
|
||||
&None | &Some(1) => self.do_slice(start, stop),
|
||||
&Some(num) => {
|
||||
match *step {
|
||||
None | Some(1) => self.do_slice(start, stop),
|
||||
Some(num) => {
|
||||
if num < 0 {
|
||||
unimplemented!("negative step indexing not yet supported")
|
||||
};
|
||||
|
||||
@@ -66,15 +66,10 @@ fn set_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
Some(iterable) => {
|
||||
let mut elements = HashMap::new();
|
||||
let iterator = objiter::get_iter(vm, iterable)?;
|
||||
loop {
|
||||
match vm.call_method(&iterator, "__next__", vec![]) {
|
||||
Ok(v) => {
|
||||
// TODO: should we use the hash function here?
|
||||
let key = v.get_id();
|
||||
elements.insert(key, v);
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
while let Ok(v) = vm.call_method(&iterator, "__next__", vec![]) {
|
||||
// TODO: should we use the hash function here?
|
||||
let key = v.get_id();
|
||||
elements.insert(key, v);
|
||||
}
|
||||
elements
|
||||
}
|
||||
@@ -151,6 +146,11 @@ fn frozenset_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
let set_type = &context.set_type;
|
||||
|
||||
let set_doc = "set() -> new empty set object\n\
|
||||
set(iterable) -> new set object\n\n\
|
||||
Build an unordered collection of unique elements.";
|
||||
|
||||
context.set_attr(
|
||||
&set_type,
|
||||
"__contains__",
|
||||
@@ -159,15 +159,26 @@ pub fn init(context: &PyContext) {
|
||||
context.set_attr(&set_type, "__len__", context.new_rustfunc(set_len));
|
||||
context.set_attr(&set_type, "__new__", context.new_rustfunc(set_new));
|
||||
context.set_attr(&set_type, "__repr__", context.new_rustfunc(set_repr));
|
||||
context.set_attr(&set_type, "__doc__", context.new_str(set_doc.to_string()));
|
||||
context.set_attr(&set_type, "add", context.new_rustfunc(set_add));
|
||||
|
||||
let frozenset_type = &context.frozenset_type;
|
||||
|
||||
let frozenset_doc = "frozenset() -> empty frozenset object\n\
|
||||
frozenset(iterable) -> frozenset object\n\n\
|
||||
Build an immutable unordered collection of unique elements.";
|
||||
|
||||
context.set_attr(
|
||||
&frozenset_type,
|
||||
"__contains__",
|
||||
context.new_rustfunc(set_contains),
|
||||
);
|
||||
context.set_attr(&frozenset_type, "__len__", context.new_rustfunc(set_len));
|
||||
context.set_attr(
|
||||
&frozenset_type,
|
||||
"__doc__",
|
||||
context.new_str(frozenset_doc.to_string()),
|
||||
);
|
||||
context.set_attr(
|
||||
&frozenset_type,
|
||||
"__repr__",
|
||||
|
||||
@@ -511,12 +511,11 @@ fn str_zfill(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
);
|
||||
let value = get_value(&s);
|
||||
let len = objint::get_value(&len).to_usize().unwrap();
|
||||
let new_str: String;
|
||||
if len <= value.len() {
|
||||
new_str = value;
|
||||
let new_str = if len <= value.len() {
|
||||
value
|
||||
} else {
|
||||
new_str = format!("{}{}", "0".repeat(len - value.len()), value);
|
||||
}
|
||||
format!("{}{}", "0".repeat(len - value.len()), value)
|
||||
};
|
||||
Ok(vm.ctx.new_str(new_str))
|
||||
}
|
||||
|
||||
@@ -572,7 +571,7 @@ fn str_index(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
Ok((start, end)) => (start, end),
|
||||
Err(e) => return Err(vm.new_index_error(e)),
|
||||
};
|
||||
let ind: usize = match value[start..end + 1].find(&sub) {
|
||||
let ind: usize = match value[start..=end].find(&sub) {
|
||||
Some(num) => num,
|
||||
None => {
|
||||
return Err(vm.new_value_error("substring not found".to_string()));
|
||||
@@ -597,7 +596,7 @@ fn str_find(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
Ok((start, end)) => (start, end),
|
||||
Err(e) => return Err(vm.new_index_error(e)),
|
||||
};
|
||||
let ind: i128 = match value[start..end + 1].find(&sub) {
|
||||
let ind: i128 = match value[start..=end].find(&sub) {
|
||||
Some(num) => num as i128,
|
||||
None => -1 as i128,
|
||||
};
|
||||
@@ -796,7 +795,7 @@ fn str_istitle(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
if value.is_empty() {
|
||||
is_titled = false;
|
||||
} else {
|
||||
for word in value.split(" ") {
|
||||
for word in value.split(' ') {
|
||||
if word != make_title(&word) {
|
||||
is_titled = false;
|
||||
break;
|
||||
@@ -887,7 +886,7 @@ fn str_rindex(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
Ok((start, end)) => (start, end),
|
||||
Err(e) => return Err(vm.new_index_error(e)),
|
||||
};
|
||||
let ind: i64 = match value[start..end + 1].rfind(&sub) {
|
||||
let ind: i64 = match value[start..=end].rfind(&sub) {
|
||||
Some(num) => num as i64,
|
||||
None => {
|
||||
return Err(vm.new_value_error("substring not found".to_string()));
|
||||
@@ -912,7 +911,7 @@ fn str_rfind(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
Ok((start, end)) => (start, end),
|
||||
Err(e) => return Err(vm.new_index_error(e)),
|
||||
};
|
||||
let ind = match value[start..end + 1].rfind(&sub) {
|
||||
let ind = match value[start..=end].rfind(&sub) {
|
||||
Some(num) => num as i128,
|
||||
None => -1 as i128,
|
||||
};
|
||||
@@ -1051,8 +1050,8 @@ pub fn subscript(vm: &mut VirtualMachine, value: &str, b: PyObjectRef) -> PyResu
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match &(*b.borrow()).payload {
|
||||
&PyObjectPayload::Slice { .. } => {
|
||||
match (*b.borrow()).payload {
|
||||
PyObjectPayload::Slice { .. } => {
|
||||
Ok(vm.new_str(value.to_string().get_slice_items(&b).to_string()))
|
||||
}
|
||||
_ => panic!(
|
||||
|
||||
@@ -109,7 +109,7 @@ fn tuple_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
if objtype::isinstance(other, &vm.ctx.tuple_type()) {
|
||||
let e1 = get_elements(zelf);
|
||||
let e2 = get_elements(other);
|
||||
let elements = e1.iter().chain(e2.iter()).map(|e| e.clone()).collect();
|
||||
let elements = e1.iter().chain(e2.iter()).cloned().collect();
|
||||
Ok(vm.ctx.new_tuple(elements))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!(
|
||||
@@ -131,7 +131,7 @@ fn tuple_count(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
for element in elements.iter() {
|
||||
let is_eq = vm._eq(element, value.clone())?;
|
||||
if objbool::boolval(vm, is_eq)? {
|
||||
count = count + 1;
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
Ok(vm.context().new_int(count))
|
||||
@@ -290,6 +290,10 @@ pub fn tuple_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
let tuple_type = &context.tuple_type;
|
||||
let tuple_doc = "tuple() -> empty tuple
|
||||
tuple(iterable) -> tuple initialized from iterable's items
|
||||
|
||||
If the argument is a tuple, the return value is the same object.";
|
||||
context.set_attr(&tuple_type, "__add__", context.new_rustfunc(tuple_add));
|
||||
context.set_attr(&tuple_type, "__eq__", context.new_rustfunc(tuple_eq));
|
||||
context.set_attr(
|
||||
@@ -313,5 +317,10 @@ pub fn init(context: &PyContext) {
|
||||
context.set_attr(&tuple_type, "__le__", context.new_rustfunc(tuple_le));
|
||||
context.set_attr(&tuple_type, "__gt__", context.new_rustfunc(tuple_gt));
|
||||
context.set_attr(&tuple_type, "__ge__", context.new_rustfunc(tuple_ge));
|
||||
context.set_attr(
|
||||
&tuple_type,
|
||||
"__doc__",
|
||||
context.new_str(tuple_doc.to_string()),
|
||||
);
|
||||
context.set_attr(&tuple_type, "index", context.new_rustfunc(tuple_index));
|
||||
}
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
use super::super::pyobject::{
|
||||
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef,
|
||||
PyResult, TypeProtocol,
|
||||
AttributeProtocol, IdProtocol, PyAttributes, PyContext, PyFuncArgs, PyObject, PyObjectPayload,
|
||||
PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objdict;
|
||||
use super::objstr;
|
||||
use super::objtype; // Required for arg_check! to use isinstance
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/*
|
||||
* The magical type type
|
||||
*/
|
||||
|
||||
pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, dict_type: PyObjectRef) {
|
||||
pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, _dict_type: PyObjectRef) {
|
||||
(*type_type.borrow_mut()).payload = PyObjectPayload::Class {
|
||||
name: String::from("type"),
|
||||
dict: objdict::new(dict_type),
|
||||
dict: RefCell::new(PyAttributes::new()),
|
||||
mro: vec![object_type],
|
||||
};
|
||||
(*type_type.borrow_mut()).typ = Some(type_type.clone());
|
||||
@@ -119,12 +120,22 @@ pub fn type_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let mut bases = vm.extract_elements(bases)?;
|
||||
bases.push(vm.context().object());
|
||||
let name = objstr::get_value(name);
|
||||
new(typ.clone(), &name, bases, dict.clone())
|
||||
new(typ.clone(), &name, bases, py_dict_to_attributes(dict))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!(": type_new: {:?}", args)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Take a python dictionary and convert it to attributes.
|
||||
fn py_dict_to_attributes(dict: &PyObjectRef) -> PyAttributes {
|
||||
let mut attrs = PyAttributes::new();
|
||||
for (key, value) in objdict::get_key_value_pairs(dict) {
|
||||
let key = objstr::get_value(&key);
|
||||
attrs.insert(key, value);
|
||||
}
|
||||
attrs
|
||||
}
|
||||
|
||||
pub fn type_call(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
|
||||
debug!("type_call: {:?}", args);
|
||||
let cls = args.shift();
|
||||
@@ -204,18 +215,16 @@ pub fn type_getattribute(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_attributes(obj: &PyObjectRef) -> HashMap<String, PyObjectRef> {
|
||||
pub fn get_attributes(obj: &PyObjectRef) -> PyAttributes {
|
||||
// Gather all members here:
|
||||
let mut attributes: HashMap<String, PyObjectRef> = HashMap::new();
|
||||
let mut attributes = PyAttributes::new();
|
||||
|
||||
// Get class attributes:
|
||||
let mut base_classes = objtype::base_classes(obj);
|
||||
base_classes.reverse();
|
||||
for bc in base_classes {
|
||||
if let PyObjectPayload::Class { dict, .. } = &bc.borrow().payload {
|
||||
let elements = objdict::get_key_value_pairs(dict);
|
||||
for (name, value) in elements.iter() {
|
||||
let name = objstr::get_value(name);
|
||||
for (name, value) in dict.borrow().iter() {
|
||||
attributes.insert(name.to_string(), value.clone());
|
||||
}
|
||||
}
|
||||
@@ -223,9 +232,7 @@ pub fn get_attributes(obj: &PyObjectRef) -> HashMap<String, PyObjectRef> {
|
||||
|
||||
// Get instance attributes:
|
||||
if let PyObjectPayload::Instance { dict } = &obj.borrow().payload {
|
||||
let elements = objdict::get_key_value_pairs(dict);
|
||||
for (name, value) in elements.iter() {
|
||||
let name = objstr::get_value(name);
|
||||
for (name, value) in dict.borrow().iter() {
|
||||
attributes.insert(name.to_string(), value.clone());
|
||||
}
|
||||
}
|
||||
@@ -242,8 +249,8 @@ fn take_next_base(
|
||||
for base in &bases {
|
||||
let head = base[0].clone();
|
||||
if !(&bases)
|
||||
.into_iter()
|
||||
.any(|x| x[1..].into_iter().any(|x| x.get_id() == head.get_id()))
|
||||
.iter()
|
||||
.any(|x| x[1..].iter().any(|x| x.get_id() == head.get_id()))
|
||||
{
|
||||
next = Some(head);
|
||||
break;
|
||||
@@ -265,7 +272,7 @@ fn linearise_mro(mut bases: Vec<Vec<PyObjectRef>>) -> Option<Vec<PyObjectRef>> {
|
||||
debug!("Linearising MRO: {:?}", bases);
|
||||
let mut result = vec![];
|
||||
loop {
|
||||
if (&bases).into_iter().all(|x| x.is_empty()) {
|
||||
if (&bases).iter().all(|x| x.is_empty()) {
|
||||
break;
|
||||
}
|
||||
match take_next_base(bases) {
|
||||
@@ -279,13 +286,18 @@ fn linearise_mro(mut bases: Vec<Vec<PyObjectRef>>) -> Option<Vec<PyObjectRef>> {
|
||||
Some(result)
|
||||
}
|
||||
|
||||
pub fn new(typ: PyObjectRef, name: &str, bases: Vec<PyObjectRef>, dict: PyObjectRef) -> PyResult {
|
||||
pub fn new(
|
||||
typ: PyObjectRef,
|
||||
name: &str,
|
||||
bases: Vec<PyObjectRef>,
|
||||
dict: HashMap<String, PyObjectRef>,
|
||||
) -> PyResult {
|
||||
let mros = bases.into_iter().map(|x| _mro(x).unwrap()).collect();
|
||||
let mro = linearise_mro(mros).unwrap();
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Class {
|
||||
name: String::from(name),
|
||||
dict,
|
||||
dict: RefCell::new(dict),
|
||||
mro,
|
||||
},
|
||||
typ,
|
||||
@@ -305,7 +317,7 @@ fn type_prepare(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{linearise_mro, new};
|
||||
use super::{IdProtocol, PyContext, PyObjectRef};
|
||||
use super::{HashMap, IdProtocol, PyContext, PyObjectRef};
|
||||
|
||||
fn map_ids(obj: Option<Vec<PyObjectRef>>) -> Option<Vec<usize>> {
|
||||
match obj {
|
||||
@@ -320,20 +332,8 @@ mod tests {
|
||||
let object = context.object;
|
||||
let type_type = context.type_type;
|
||||
|
||||
let a = new(
|
||||
type_type.clone(),
|
||||
"A",
|
||||
vec![object.clone()],
|
||||
type_type.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
let b = new(
|
||||
type_type.clone(),
|
||||
"B",
|
||||
vec![object.clone()],
|
||||
type_type.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
let a = new(type_type.clone(), "A", vec![object.clone()], HashMap::new()).unwrap();
|
||||
let b = new(type_type.clone(), "B", vec![object.clone()], HashMap::new()).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
map_ids(linearise_mro(vec![
|
||||
|
||||
@@ -70,6 +70,10 @@ pub type PyObjectWeakRef = Weak<RefCell<PyObject>>;
|
||||
/// since exceptions are also python objects.
|
||||
pub type PyResult = Result<PyObjectRef, PyObjectRef>; // A valid value, or an exception
|
||||
|
||||
/// For attributes we do not use a dict, but a hashmap. This is probably
|
||||
/// faster, unordered, and only supports strings as keys.
|
||||
pub type PyAttributes = HashMap<String, PyObjectRef>;
|
||||
|
||||
impl fmt::Display for PyObject {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use self::TypeProtocol;
|
||||
@@ -161,14 +165,9 @@ pub fn create_type(
|
||||
name: &str,
|
||||
type_type: &PyObjectRef,
|
||||
base: &PyObjectRef,
|
||||
dict_type: &PyObjectRef,
|
||||
_dict_type: &PyObjectRef,
|
||||
) -> PyObjectRef {
|
||||
let dict = PyObject::new(
|
||||
PyObjectPayload::Dict {
|
||||
elements: HashMap::new(),
|
||||
},
|
||||
dict_type.clone(),
|
||||
);
|
||||
let dict = PyAttributes::new();
|
||||
objtype::new(type_type.clone(), name, vec![base.clone()], dict).unwrap()
|
||||
}
|
||||
|
||||
@@ -411,12 +410,7 @@ impl PyContext {
|
||||
}
|
||||
|
||||
pub fn new_object(&self) -> PyObjectRef {
|
||||
PyObject::new(
|
||||
PyObjectPayload::Instance {
|
||||
dict: self.new_dict(),
|
||||
},
|
||||
self.object(),
|
||||
)
|
||||
self.new_instance(self.object(), None)
|
||||
}
|
||||
|
||||
pub fn new_int<T: ToBigInt>(&self, i: T) -> PyObjectRef {
|
||||
@@ -482,7 +476,7 @@ impl PyContext {
|
||||
}
|
||||
|
||||
pub fn new_class(&self, name: &str, base: PyObjectRef) -> PyObjectRef {
|
||||
objtype::new(self.type_type(), name, vec![base], self.new_dict()).unwrap()
|
||||
objtype::new(self.type_type(), name, vec![base], PyAttributes::new()).unwrap()
|
||||
}
|
||||
|
||||
pub fn new_scope(&self, parent: Option<PyObjectRef>) -> PyObjectRef {
|
||||
@@ -536,12 +530,7 @@ impl PyContext {
|
||||
function: F,
|
||||
) -> PyObjectRef {
|
||||
let fget = self.new_rustfunc(function);
|
||||
let py_obj = PyObject::new(
|
||||
PyObjectPayload::Instance {
|
||||
dict: self.new_dict(),
|
||||
},
|
||||
self.property_type(),
|
||||
);
|
||||
let py_obj = self.new_instance(self.property_type(), None);
|
||||
self.set_attr(&py_obj, "fget", fget.clone());
|
||||
py_obj
|
||||
}
|
||||
@@ -577,13 +566,23 @@ impl PyContext {
|
||||
&self,
|
||||
function: F,
|
||||
) -> PyObjectRef {
|
||||
let dict = self.new_dict();
|
||||
self.set_item(&dict, "function", self.new_rustfunc(function));
|
||||
self.new_instance(dict, self.member_descriptor_type())
|
||||
let mut dict = PyAttributes::new();
|
||||
dict.insert("function".to_string(), self.new_rustfunc(function));
|
||||
self.new_instance(self.member_descriptor_type(), Some(dict))
|
||||
}
|
||||
|
||||
pub fn new_instance(&self, dict: PyObjectRef, class: PyObjectRef) -> PyObjectRef {
|
||||
PyObject::new(PyObjectPayload::Instance { dict }, class)
|
||||
pub fn new_instance(&self, class: PyObjectRef, dict: Option<PyAttributes>) -> PyObjectRef {
|
||||
let dict = if let Some(dict) = dict {
|
||||
dict
|
||||
} else {
|
||||
PyAttributes::new()
|
||||
};
|
||||
PyObject::new(
|
||||
PyObjectPayload::Instance {
|
||||
dict: RefCell::new(dict),
|
||||
},
|
||||
class,
|
||||
)
|
||||
}
|
||||
|
||||
// Item set/get:
|
||||
@@ -611,8 +610,9 @@ impl PyContext {
|
||||
pub fn set_attr(&self, obj: &PyObjectRef, attr_name: &str, value: PyObjectRef) {
|
||||
match obj.borrow().payload {
|
||||
PyObjectPayload::Module { ref dict, .. } => self.set_item(dict, attr_name, value),
|
||||
PyObjectPayload::Instance { ref dict } => self.set_item(dict, attr_name, value),
|
||||
PyObjectPayload::Class { ref dict, .. } => self.set_item(dict, attr_name, value),
|
||||
PyObjectPayload::Instance { ref dict } | PyObjectPayload::Class { ref dict, .. } => {
|
||||
dict.borrow_mut().insert(attr_name.to_string(), value);
|
||||
}
|
||||
ref payload => unimplemented!("set_attr unimplemented for: {:?}", payload),
|
||||
};
|
||||
}
|
||||
@@ -673,10 +673,7 @@ pub trait ParentProtocol {
|
||||
impl ParentProtocol for PyObjectRef {
|
||||
fn has_parent(&self) -> bool {
|
||||
match self.borrow().payload {
|
||||
PyObjectPayload::Scope { ref scope } => match scope.parent {
|
||||
Some(_) => true,
|
||||
None => false,
|
||||
},
|
||||
PyObjectPayload::Scope { ref scope } => scope.parent.is_some(),
|
||||
_ => panic!("Only scopes have parent (not {:?}", self),
|
||||
}
|
||||
}
|
||||
@@ -700,7 +697,7 @@ pub trait AttributeProtocol {
|
||||
fn class_get_item(class: &PyObjectRef, attr_name: &str) -> Option<PyObjectRef> {
|
||||
let class = class.borrow();
|
||||
match class.payload {
|
||||
PyObjectPayload::Class { ref dict, .. } => dict.get_item(attr_name),
|
||||
PyObjectPayload::Class { ref dict, .. } => dict.borrow().get(attr_name).map(|v| v.clone()),
|
||||
_ => panic!("Only classes should be in MRO!"),
|
||||
}
|
||||
}
|
||||
@@ -708,7 +705,7 @@ fn class_get_item(class: &PyObjectRef, attr_name: &str) -> Option<PyObjectRef> {
|
||||
fn class_has_item(class: &PyObjectRef, attr_name: &str) -> bool {
|
||||
let class = class.borrow();
|
||||
match class.payload {
|
||||
PyObjectPayload::Class { ref dict, .. } => dict.contains_key(attr_name),
|
||||
PyObjectPayload::Class { ref dict, .. } => dict.borrow().contains_key(attr_name),
|
||||
_ => panic!("Only classes should be in MRO!"),
|
||||
}
|
||||
}
|
||||
@@ -729,7 +726,9 @@ impl AttributeProtocol for PyObjectRef {
|
||||
}
|
||||
None
|
||||
}
|
||||
PyObjectPayload::Instance { ref dict } => dict.get_item(attr_name),
|
||||
PyObjectPayload::Instance { ref dict } => {
|
||||
dict.borrow().get(attr_name).map(|v| v.clone())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -739,10 +738,9 @@ impl AttributeProtocol for PyObjectRef {
|
||||
match obj.payload {
|
||||
PyObjectPayload::Module { ref dict, .. } => dict.contains_key(attr_name),
|
||||
PyObjectPayload::Class { ref mro, .. } => {
|
||||
class_has_item(self, attr_name)
|
||||
|| mro.into_iter().any(|d| class_has_item(d, attr_name))
|
||||
class_has_item(self, attr_name) || mro.iter().any(|d| class_has_item(d, attr_name))
|
||||
}
|
||||
PyObjectPayload::Instance { ref dict } => dict.contains_key(attr_name),
|
||||
PyObjectPayload::Instance { ref dict } => dict.borrow().contains_key(attr_name),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@@ -935,14 +933,14 @@ pub enum PyObjectPayload {
|
||||
None,
|
||||
Class {
|
||||
name: String,
|
||||
dict: PyObjectRef,
|
||||
dict: RefCell<PyAttributes>,
|
||||
mro: Vec<PyObjectRef>,
|
||||
},
|
||||
WeakRef {
|
||||
referent: PyObjectWeakRef,
|
||||
},
|
||||
Instance {
|
||||
dict: PyObjectRef,
|
||||
dict: RefCell<PyAttributes>,
|
||||
},
|
||||
RustFunction {
|
||||
function: Box<Fn(&mut VirtualMachine, PyFuncArgs) -> PyResult>,
|
||||
|
||||
@@ -45,8 +45,7 @@ fn program_to_ast(ctx: &PyContext, program: &ast::Program) -> PyObjectRef {
|
||||
fn create_node(ctx: &PyContext, _name: &str) -> PyObjectRef {
|
||||
// TODO: instantiate a class of type given by name
|
||||
// TODO: lookup in the current module?
|
||||
let node = ctx.new_object();
|
||||
node
|
||||
ctx.new_object()
|
||||
}
|
||||
|
||||
fn statements_to_ast(ctx: &PyContext, statements: &[ast::LocatedStatement]) -> PyObjectRef {
|
||||
@@ -99,18 +98,9 @@ fn statement_to_ast(ctx: &PyContext, statement: &ast::LocatedStatement) -> PyObj
|
||||
ctx.set_attr(&node, "decorator_list", py_decorator_list);
|
||||
node
|
||||
}
|
||||
ast::Statement::Continue => {
|
||||
let node = create_node(ctx, "Continue");
|
||||
node
|
||||
}
|
||||
ast::Statement::Break => {
|
||||
let node = create_node(ctx, "Break");
|
||||
node
|
||||
}
|
||||
ast::Statement::Pass => {
|
||||
let node = create_node(ctx, "Pass");
|
||||
node
|
||||
}
|
||||
ast::Statement::Continue => create_node(ctx, "Continue"),
|
||||
ast::Statement::Break => create_node(ctx, "Break"),
|
||||
ast::Statement::Pass => create_node(ctx, "Pass"),
|
||||
ast::Statement::Assert { test, msg } => {
|
||||
let node = create_node(ctx, "Pass");
|
||||
|
||||
@@ -127,12 +117,8 @@ fn statement_to_ast(ctx: &PyContext, statement: &ast::LocatedStatement) -> PyObj
|
||||
ast::Statement::Delete { targets } => {
|
||||
let node = create_node(ctx, "Delete");
|
||||
|
||||
let py_targets = ctx.new_tuple(
|
||||
targets
|
||||
.into_iter()
|
||||
.map(|v| expression_to_ast(ctx, v))
|
||||
.collect(),
|
||||
);
|
||||
let py_targets =
|
||||
ctx.new_tuple(targets.iter().map(|v| expression_to_ast(ctx, v)).collect());
|
||||
ctx.set_attr(&node, "targets", py_targets);
|
||||
|
||||
node
|
||||
@@ -141,12 +127,7 @@ fn statement_to_ast(ctx: &PyContext, statement: &ast::LocatedStatement) -> PyObj
|
||||
let node = create_node(ctx, "Return");
|
||||
|
||||
let py_value = if let Some(value) = value {
|
||||
ctx.new_tuple(
|
||||
value
|
||||
.into_iter()
|
||||
.map(|v| expression_to_ast(ctx, v))
|
||||
.collect(),
|
||||
)
|
||||
ctx.new_tuple(value.iter().map(|v| expression_to_ast(ctx, v)).collect())
|
||||
} else {
|
||||
ctx.none()
|
||||
};
|
||||
|
||||
@@ -27,7 +27,7 @@ use super::super::pyobject::{
|
||||
use super::super::vm::VirtualMachine;
|
||||
|
||||
fn compute_c_flag(mode: &str) -> u16 {
|
||||
match mode.as_ref() {
|
||||
match mode {
|
||||
"w" => 512,
|
||||
"x" => 512,
|
||||
"a" => 8,
|
||||
@@ -85,11 +85,8 @@ fn buffered_reader_read(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
.map_err(|_| vm.new_value_error("IO Error".to_string()))?;
|
||||
|
||||
//Copy bytes from the buffer vector into the results vector
|
||||
match buffer.borrow_mut().payload {
|
||||
PyObjectPayload::Bytes { ref mut value } => {
|
||||
result.extend(value.iter().cloned());
|
||||
}
|
||||
_ => {}
|
||||
if let PyObjectPayload::Bytes { ref mut value } = buffer.borrow_mut().payload {
|
||||
result.extend(value.iter().cloned());
|
||||
};
|
||||
|
||||
let len = vm.get_method(buffer.clone(), &"__len__".to_string());
|
||||
@@ -171,16 +168,14 @@ fn file_io_readinto(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let handle = os::rust_file(raw_fd);
|
||||
|
||||
let mut f = handle.take(length);
|
||||
match obj.borrow_mut().payload {
|
||||
if let PyObjectPayload::Bytes { ref mut value } = obj.borrow_mut().payload {
|
||||
//TODO: Implement for MemoryView
|
||||
PyObjectPayload::Bytes { ref mut value } => {
|
||||
value.clear();
|
||||
match f.read_to_end(&mut *value) {
|
||||
Ok(_) => {}
|
||||
Err(_) => return Err(vm.new_value_error("Error reading from Take".to_string())),
|
||||
}
|
||||
|
||||
value.clear();
|
||||
match f.read_to_end(&mut *value) {
|
||||
Ok(_) => {}
|
||||
Err(_) => return Err(vm.new_value_error("Error reading from Take".to_string())),
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
let updated = os::raw_file_number(f.into_inner());
|
||||
@@ -318,7 +313,7 @@ pub fn io_open(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
//the operation in the mode.
|
||||
//There are 3 possible classes here, each inheriting from the RawBaseIO
|
||||
// creating || writing || appending => BufferedWriter
|
||||
let buffered = if rust_mode.contains("w") {
|
||||
let buffered = if rust_mode.contains('w') {
|
||||
vm.invoke(
|
||||
buffered_writer_class,
|
||||
PyFuncArgs::new(vec![file_io.clone()], vec![]),
|
||||
@@ -332,7 +327,7 @@ pub fn io_open(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
//TODO: updating => PyBufferedRandom
|
||||
};
|
||||
|
||||
if rust_mode.contains("t") {
|
||||
if rust_mode.contains('t') {
|
||||
//If the mode is text this buffer type is consumed on construction of
|
||||
//a TextIOWrapper which is subsequently returned.
|
||||
vm.invoke(
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
*/
|
||||
|
||||
use super::super::obj::{objsequence, objstr, objtype};
|
||||
use super::super::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use super::super::pyobject::{
|
||||
PyAttributes, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::VirtualMachine;
|
||||
|
||||
fn types_new_class(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
@@ -15,7 +17,6 @@ fn types_new_class(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
);
|
||||
|
||||
let name = objstr::get_value(name);
|
||||
let dict = vm.ctx.new_dict();
|
||||
|
||||
let bases = match bases {
|
||||
Some(b) => {
|
||||
@@ -28,7 +29,7 @@ fn types_new_class(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
None => vec![vm.ctx.object()],
|
||||
};
|
||||
|
||||
objtype::new(vm.ctx.type_type(), &name, bases, dict)
|
||||
objtype::new(vm.ctx.type_type(), &name, bases, PyAttributes::new())
|
||||
}
|
||||
|
||||
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
||||
|
||||
@@ -91,8 +91,7 @@ impl VirtualMachine {
|
||||
};
|
||||
|
||||
// Call function:
|
||||
let exception = self.invoke(exc_type, args).unwrap();
|
||||
exception
|
||||
self.invoke(exc_type, args).unwrap()
|
||||
}
|
||||
|
||||
pub fn new_type_error(&mut self, msg: String) -> PyObjectRef {
|
||||
|
||||
Reference in New Issue
Block a user