Able to create set from iterable.

This commit is contained in:
Matthew Constable
2019-02-03 17:25:24 +00:00
parent b433b7fcf0
commit da5046100b
3 changed files with 34 additions and 42 deletions

View File

@@ -230,10 +230,8 @@ impl Frame {
Ok(None)
}
bytecode::Instruction::BuildSet { size, unpack } => {
let elements = self.get_elements(vm, *size, *unpack)?;
let _elements = self.get_elements(vm, *size, *unpack)?;
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)
}

View File

@@ -3,8 +3,7 @@
*/
use super::super::pyobject::{
IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult,
TypeProtocol,
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
};
use super::super::vm::VirtualMachine;
use super::objbool;
@@ -23,15 +22,6 @@ pub fn get_elements(obj: &PyObjectRef) -> HashMap<BigInt, PyObjectRef> {
}
}
pub fn sequence_to_hashmap(iterable: &Vec<PyObjectRef>) -> HashMap<usize, PyObjectRef> {
let mut elements = HashMap::new();
for item in iterable {
let key = item.get_id();
elements.insert(key, item.clone());
}
elements
}
fn perform_action_with_hash(vm: &mut VirtualMachine, elements: &mut HashMap<BigInt, PyObjectRef>, item: &PyObjectRef,
f: &Fn(&mut VirtualMachine, &mut HashMap<BigInt, PyObjectRef>, BigInt, &PyObjectRef) -> PyResult) -> PyResult {
let hash_result: PyResult = vm.call_method(item, "__hash__", vec![]);
@@ -50,6 +40,16 @@ fn perform_action_with_hash(vm: &mut VirtualMachine, elements: &mut HashMap<BigI
}
}
fn insert_into_set(vm: &mut VirtualMachine, elements: &mut HashMap<BigInt, PyObjectRef>, item: &PyObjectRef) -> PyResult
{
fn insert(vm: &mut VirtualMachine, elements: &mut HashMap<BigInt, PyObjectRef>,
key: BigInt, value: &PyObjectRef) -> PyResult {
elements.insert(key, value.clone());
Ok(vm.get_none())
}
perform_action_with_hash(vm, elements, item, &insert)
}
fn set_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
trace!("set.add called with: {:?}", args);
arg_check!(
@@ -60,13 +60,7 @@ fn set_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let mut mut_obj = s.borrow_mut();
match mut_obj.payload {
PyObjectPayload::Set {ref mut elements} => {
fn insert_into_set(vm: &mut VirtualMachine, elements: &mut HashMap<BigInt, PyObjectRef>,
key: BigInt, value: &PyObjectRef) -> PyResult {
elements.insert(key, value.clone());
Ok(vm.get_none())
}
perform_action_with_hash(vm, elements, item, &insert_into_set)},
PyObjectPayload::Set {ref mut elements} => insert_into_set(vm, elements, item),
_ => Err(vm.new_type_error("set.add is called with no item".to_string())),
}
}
@@ -82,7 +76,7 @@ fn set_remove(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
match mut_obj.payload {
PyObjectPayload::Set {ref mut elements} => {
fn remove_from_set(vm: &mut VirtualMachine, elements: &mut HashMap<BigInt, PyObjectRef>,
fn remove(vm: &mut VirtualMachine, elements: &mut HashMap<BigInt, PyObjectRef>,
key: BigInt, value: &PyObjectRef) -> PyResult {
match elements.remove(&key) {
None => {
@@ -92,7 +86,7 @@ fn set_remove(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Some(_) => {Ok(vm.get_none())},
}
}
perform_action_with_hash(vm, elements, item, &remove_from_set)},
perform_action_with_hash(vm, elements, item, &remove)},
_ => Err(vm.new_type_error("set.remove is called with no item".to_string())),
}
}
@@ -110,27 +104,25 @@ 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: HashMap<BigInt, PyObjectRef> = 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) => {
insert_into_set(vm, &mut elements, &v).unwrap();
}
_ => break,
}
}
elements
}
};
Ok(PyObject::new(
PyObjectPayload::Set { elements: HashMap::new() },
PyObjectPayload::Set { elements: elements },
cls.clone(),
))
}

View File

@@ -441,6 +441,8 @@ impl PyContext {
}
pub fn new_set(&self) -> PyObjectRef {
// Initialized empty, as calling __hash__ is required for adding each object to the set
// which requires a VM context - this is done in the objset code itself.
let elements: HashMap<BigInt, PyObjectRef> = HashMap::new();
PyObject::new(PyObjectPayload::Set { elements: elements }, self.set_type())
}