mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-17 01:51:39 +09:00
Sets use python __hash__ functions when items are added - need to re-implement set creation from iterable
This commit is contained in:
@@ -231,7 +231,9 @@ impl Frame {
|
||||
}
|
||||
bytecode::Instruction::BuildSet { size, unpack } => {
|
||||
let elements = self.get_elements(vm, *size, *unpack)?;
|
||||
let py_obj = vm.ctx.new_set(elements);
|
||||
let py_obj = vm.ctx.new_set();
|
||||
// TODO: Allow initial population of set with iterable (note: __hash__() of each object being added
|
||||
// requires access to the VM. (see set_add in objset.rs)
|
||||
self.push_value(py_obj);
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
@@ -13,8 +13,9 @@ use super::objstr;
|
||||
use super::objtype;
|
||||
use num_bigint::ToBigInt;
|
||||
use std::collections::HashMap;
|
||||
use num_bigint::BigInt;
|
||||
|
||||
pub fn get_elements(obj: &PyObjectRef) -> HashMap<usize, PyObjectRef> {
|
||||
pub fn get_elements(obj: &PyObjectRef) -> HashMap<BigInt, PyObjectRef> {
|
||||
if let PyObjectPayload::Set { elements } = &obj.borrow().payload {
|
||||
elements.clone()
|
||||
} else {
|
||||
@@ -40,15 +41,47 @@ fn set_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
);
|
||||
let mut mut_obj = s.borrow_mut();
|
||||
|
||||
if let PyObjectPayload::Set { ref mut elements } = mut_obj.payload {
|
||||
let key = item.get_id();
|
||||
elements.insert(key, item.clone());
|
||||
Ok(vm.get_none())
|
||||
} else {
|
||||
Err(vm.new_type_error("set.add is called with no list".to_string()))
|
||||
match mut_obj.payload {
|
||||
PyObjectPayload::Set { ref mut elements } => {
|
||||
let hash_result: PyObjectRef = vm.call_method(item, "__hash__", vec![]).unwrap();
|
||||
let hash_object = hash_result.borrow();
|
||||
let key: BigInt;
|
||||
match hash_object.payload {
|
||||
PyObjectPayload::Integer { ref value } => {
|
||||
let key = value.clone();
|
||||
elements.insert(key, item.clone());
|
||||
Ok(vm.get_none())
|
||||
},
|
||||
_ => { Err(vm.new_attribute_error(format!("Expected item to implment __hash__"))) }
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
Err(vm.new_type_error("set.add is called with no list".to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//fn set_remove(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
// trace!("set.remove called with: {:?}", args);
|
||||
// arg_check!(
|
||||
// vm,
|
||||
// args,
|
||||
// required = [(s, Some(vm.ctx.set_type())), (item, None)]
|
||||
// );
|
||||
// let mut mut_obj = s.borrow_mut();
|
||||
//
|
||||
// match mut_obj.payload {
|
||||
// PyObjectPayload::Set { ref mut elements } => {
|
||||
// let key = item.get_id();
|
||||
// elements.remove(&key);
|
||||
// Ok(vm.get_none())
|
||||
// },
|
||||
// _ => {
|
||||
// Err(vm.new_key_error("set.remove is called with no element".to_string()))
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
/* Create a new object of sub-type of set */
|
||||
fn set_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
@@ -62,27 +95,27 @@ fn set_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
return Err(vm.new_type_error(format!("{} is not a subtype of set", cls.borrow())));
|
||||
}
|
||||
|
||||
let elements = match iterable {
|
||||
None => HashMap::new(),
|
||||
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,
|
||||
}
|
||||
}
|
||||
elements
|
||||
}
|
||||
};
|
||||
// let elements = match iterable {
|
||||
// None => HashMap::new(),
|
||||
// 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,
|
||||
// }
|
||||
// }
|
||||
// elements
|
||||
// }
|
||||
// };
|
||||
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Set { elements: elements },
|
||||
PyObjectPayload::Set { elements: HashMap::new() },
|
||||
cls.clone(),
|
||||
))
|
||||
}
|
||||
@@ -161,6 +194,7 @@ pub fn init(context: &PyContext) {
|
||||
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, "add", context.new_rustfunc(set_add));
|
||||
// context.set_attr(&set_type, "remove", context.new_rustfunc(set_remove));
|
||||
|
||||
let ref frozenset_type = context.frozenset_type;
|
||||
context.set_attr(
|
||||
|
||||
@@ -440,8 +440,8 @@ impl PyContext {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_set(&self, elements: Vec<PyObjectRef>) -> PyObjectRef {
|
||||
let elements = objset::sequence_to_hashmap(&elements);
|
||||
pub fn new_set(&self) -> PyObjectRef {
|
||||
let elements: HashMap<BigInt, PyObjectRef> = HashMap::new();
|
||||
PyObject::new(PyObjectPayload::Set { elements: elements }, self.set_type())
|
||||
}
|
||||
|
||||
@@ -871,7 +871,7 @@ pub enum PyObjectPayload {
|
||||
elements: objdict::DictContentType,
|
||||
},
|
||||
Set {
|
||||
elements: HashMap<usize, PyObjectRef>,
|
||||
elements: HashMap<BigInt, PyObjectRef>,
|
||||
},
|
||||
Iterator {
|
||||
position: usize,
|
||||
|
||||
@@ -100,6 +100,11 @@ impl VirtualMachine {
|
||||
self.new_exception(type_error, msg)
|
||||
}
|
||||
|
||||
pub fn new_attribute_error(&mut self, msg: String) -> PyObjectRef {
|
||||
let type_error = self.ctx.exceptions.attribute_error.clone();
|
||||
self.new_exception(type_error, msg)
|
||||
}
|
||||
|
||||
/// Create a new python ValueError object. Useful for raising errors from
|
||||
/// python functions implemented in rust.
|
||||
pub fn new_value_error(&mut self, msg: String) -> PyObjectRef {
|
||||
|
||||
Reference in New Issue
Block a user