From a7f97671ac06c8e8ccc47d8f42d90234fd7cb388 Mon Sep 17 00:00:00 2001 From: Jeong Yunwon Date: Mon, 30 May 2022 09:48:50 +0900 Subject: [PATCH] move generic slots to protocol module --- vm/src/protocol/mapping.rs | 73 ++++++++++++ vm/src/protocol/number.rs | 52 +++++++++ vm/src/protocol/sequence.rs | 52 +++++++++ vm/src/types/slot.rs | 213 +++--------------------------------- 4 files changed, 190 insertions(+), 200 deletions(-) diff --git a/vm/src/protocol/mapping.rs b/vm/src/protocol/mapping.rs index 48663e7a8f..98a45038fe 100644 --- a/vm/src/protocol/mapping.rs +++ b/vm/src/protocol/mapping.rs @@ -27,6 +27,79 @@ impl PyMappingMethods { fn check(&self) -> bool { self.subscript.is_some() } + + pub(crate) fn generic( + has_length: bool, + has_subscript: bool, + has_ass_subscript: bool, + ) -> &'static Self { + static METHODS: &[PyMappingMethods] = &[ + new_generic(false, false, false), + new_generic(true, false, false), + new_generic(false, true, false), + new_generic(true, true, false), + new_generic(false, false, true), + new_generic(true, false, true), + new_generic(false, true, true), + new_generic(true, true, true), + ]; + + fn length(mapping: &PyMapping, vm: &VirtualMachine) -> PyResult { + crate::types::slot_length(mapping.obj, vm) + } + fn subscript(mapping: &PyMapping, needle: &PyObject, vm: &VirtualMachine) -> PyResult { + vm.call_special_method( + mapping.obj.to_owned(), + identifier!(vm, __getitem__), + (needle.to_owned(),), + ) + } + fn ass_subscript( + mapping: &PyMapping, + needle: &PyObject, + value: Option, + vm: &VirtualMachine, + ) -> PyResult<()> { + match value { + Some(value) => vm + .call_special_method( + mapping.obj.to_owned(), + identifier!(vm, __setitem__), + (needle.to_owned(), value), + ) + .map(|_| Ok(()))?, + None => vm + .call_special_method( + mapping.obj.to_owned(), + identifier!(vm, __delitem__), + (needle.to_owned(),), + ) + .map(|_| Ok(()))?, + } + } + + const fn new_generic( + has_length: bool, + has_subscript: bool, + has_ass_subscript: bool, + ) -> PyMappingMethods { + PyMappingMethods { + length: if has_length { Some(length) } else { None }, + subscript: if has_subscript { Some(subscript) } else { None }, + ass_subscript: if has_ass_subscript { + Some(ass_subscript) + } else { + None + }, + } + } + + let key = (has_length as usize) + | ((has_subscript as usize) << 1) + | ((has_ass_subscript as usize) << 2); + + &METHODS[key] + } } #[derive(Clone)] diff --git a/vm/src/protocol/number.rs b/vm/src/protocol/number.rs index f2420f709b..2c2100168f 100644 --- a/vm/src/protocol/number.rs +++ b/vm/src/protocol/number.rs @@ -92,6 +92,58 @@ impl PyNumberMethods { matrix_multiply: None, inplace_matrix_multiply: None, }; + + pub(crate) fn generic( + has_int: bool, + has_float: bool, + has_index: bool, + ) -> &'static PyNumberMethods { + static METHODS: &[PyNumberMethods] = &[ + new_generic(false, false, false), + new_generic(true, false, false), + new_generic(false, true, false), + new_generic(true, true, false), + new_generic(false, false, true), + new_generic(true, false, true), + new_generic(false, true, true), + new_generic(true, true, true), + ]; + + fn int(num: &PyNumber, vm: &VirtualMachine) -> PyResult> { + let ret = vm.call_special_method(num.obj.to_owned(), identifier!(vm, __int__), ())?; + ret.downcast::().map_err(|obj| { + vm.new_type_error(format!("__int__ returned non-int (type {})", obj.class())) + }) + } + fn float(num: &PyNumber, vm: &VirtualMachine) -> PyResult> { + let ret = vm.call_special_method(num.obj.to_owned(), identifier!(vm, __float__), ())?; + ret.downcast::().map_err(|obj| { + vm.new_type_error(format!( + "__float__ returned non-float (type {})", + obj.class() + )) + }) + } + fn index(num: &PyNumber, vm: &VirtualMachine) -> PyResult> { + let ret = vm.call_special_method(num.obj.to_owned(), identifier!(vm, __index__), ())?; + ret.downcast::().map_err(|obj| { + vm.new_type_error(format!("__index__ returned non-int (type {})", obj.class())) + }) + } + + const fn new_generic(has_int: bool, has_float: bool, has_index: bool) -> PyNumberMethods { + PyNumberMethods { + int: if has_int { Some(int) } else { None }, + float: if has_float { Some(float) } else { None }, + index: if has_index { Some(index) } else { None }, + ..PyNumberMethods::NOT_IMPLEMENTED + } + } + + let key = (has_int as usize) | ((has_float as usize) << 1) | ((has_index as usize) << 2); + + &METHODS[key] + } } pub struct PyNumber<'a> { diff --git a/vm/src/protocol/sequence.rs b/vm/src/protocol/sequence.rs index fd87c8a1ff..c279dcb8df 100644 --- a/vm/src/protocol/sequence.rs +++ b/vm/src/protocol/sequence.rs @@ -39,6 +39,58 @@ impl PySequenceMethods { pub fn check(&self) -> bool { self.item.is_some() } + + pub(crate) fn generic(has_length: bool, has_ass_item: bool) -> &'static PySequenceMethods { + static METHODS: &[PySequenceMethods] = &[ + new_generic(false, false), + new_generic(true, false), + new_generic(false, true), + new_generic(true, true), + ]; + + fn length(seq: &PySequence, vm: &VirtualMachine) -> PyResult { + crate::types::slot_length(seq.obj, vm) + } + fn item(seq: &PySequence, i: isize, vm: &VirtualMachine) -> PyResult { + vm.call_special_method(seq.obj.to_owned(), identifier!(vm, __getitem__), (i,)) + } + fn ass_item( + seq: &PySequence, + i: isize, + value: Option, + vm: &VirtualMachine, + ) -> PyResult<()> { + match value { + Some(value) => vm + .call_special_method( + seq.obj.to_owned(), + identifier!(vm, __setitem__), + (i.to_pyobject(vm), value), + ) + .map(|_| Ok(()))?, + None => vm + .call_special_method( + seq.obj.to_owned(), + identifier!(vm, __delitem__), + (i.to_pyobject(vm),), + ) + .map(|_| Ok(()))?, + } + } + + const fn new_generic(has_length: bool, has_ass_item: bool) -> PySequenceMethods { + PySequenceMethods { + length: if has_length { Some(length) } else { None }, + item: Some(item), + ass_item: if has_ass_item { Some(ass_item) } else { None }, + ..PySequenceMethods::NOT_IMPLEMENTED + } + } + + let key = (has_length as usize) | ((has_ass_item as usize) << 1); + + &METHODS[key] + } } impl Debug for PySequenceMethods { diff --git a/vm/src/types/slot.rs b/vm/src/types/slot.rs index ae3099a284..8212ce0f21 100644 --- a/vm/src/types/slot.rs +++ b/vm/src/types/slot.rs @@ -1,8 +1,8 @@ use crate::common::{hash::PyHash, lock::PyRwLock}; use crate::{ - builtins::{PyFloat, PyInt, PyStrInterned, PyStrRef, PyType, PyTypeRef}, + builtins::{PyInt, PyStrInterned, PyStrRef, PyType, PyTypeRef}, bytecode::ComparisonOperator, - convert::{ToPyObject, ToPyResult}, + convert::ToPyResult, function::Either, function::{FromArgs, FuncArgs, OptionalArg, PyComparisonValue}, identifier, @@ -163,7 +163,8 @@ pub(crate) type InitFunc = fn(PyObjectRef, FuncArgs, &VirtualMachine) -> PyResul pub(crate) type DelFunc = fn(&PyObject, &VirtualMachine) -> PyResult<()>; pub(crate) type AsSequenceFunc = fn(&PyObject, &VirtualMachine) -> &'static PySequenceMethods; -fn length_wrapper(obj: &PyObject, vm: &VirtualMachine) -> PyResult { +// slot_sq_length +pub(crate) fn slot_length(obj: &PyObject, vm: &VirtualMachine) -> PyResult { let ret = vm.call_special_method(obj.to_owned(), identifier!(vm, __len__), ())?; let len = ret.payload::().ok_or_else(|| { vm.new_type_error(format!( @@ -181,152 +182,17 @@ fn length_wrapper(obj: &PyObject, vm: &VirtualMachine) -> PyResult { Ok(len as usize) } -const fn bool_int(v: bool) -> usize { - if v { - 1 - } else { - 0 - } -} - -pub(crate) fn static_as_mapping_generic( - has_length: bool, - has_subscript: bool, - has_ass_subscript: bool, -) -> &'static PyMappingMethods { - static METHODS: &[PyMappingMethods] = &[ - new_generic(false, false, false), - new_generic(true, false, false), - new_generic(false, true, false), - new_generic(true, true, false), - new_generic(false, false, true), - new_generic(true, false, true), - new_generic(false, true, true), - new_generic(true, true, true), - ]; - - fn length(mapping: &PyMapping, vm: &VirtualMachine) -> PyResult { - length_wrapper(mapping.obj, vm) - } - fn subscript(mapping: &PyMapping, needle: &PyObject, vm: &VirtualMachine) -> PyResult { - vm.call_special_method( - mapping.obj.to_owned(), - identifier!(vm, __getitem__), - (needle.to_owned(),), - ) - } - fn ass_subscript( - mapping: &PyMapping, - needle: &PyObject, - value: Option, - vm: &VirtualMachine, - ) -> PyResult<()> { - match value { - Some(value) => vm - .call_special_method( - mapping.obj.to_owned(), - identifier!(vm, __setitem__), - (needle.to_owned(), value), - ) - .map(|_| Ok(()))?, - None => vm - .call_special_method( - mapping.obj.to_owned(), - identifier!(vm, __delitem__), - (needle.to_owned(),), - ) - .map(|_| Ok(()))?, - } - } - - const fn new_generic( - has_length: bool, - has_subscript: bool, - has_ass_subscript: bool, - ) -> PyMappingMethods { - PyMappingMethods { - length: if has_length { Some(length) } else { None }, - subscript: if has_subscript { Some(subscript) } else { None }, - ass_subscript: if has_ass_subscript { - Some(ass_subscript) - } else { - None - }, - } - } - - let key = - bool_int(has_length) | (bool_int(has_subscript) << 1) | (bool_int(has_ass_subscript) << 2); - - &METHODS[key] -} - -fn as_mapping_generic(zelf: &PyObject, vm: &VirtualMachine) -> &'static PyMappingMethods { +fn slot_as_mapping(zelf: &PyObject, vm: &VirtualMachine) -> &'static PyMappingMethods { let (has_length, has_subscript, has_ass_subscript) = ( zelf.class().has_attr(identifier!(vm, __len__)), zelf.class().has_attr(identifier!(vm, __getitem__)), zelf.class().has_attr(identifier!(vm, __setitem__)) | zelf.class().has_attr(identifier!(vm, __delitem__)), ); - static_as_mapping_generic(has_length, has_subscript, has_ass_subscript) -} - -pub(crate) fn static_as_sequence_generic( - has_length: bool, - has_ass_item: bool, -) -> &'static PySequenceMethods { - static METHODS: &[PySequenceMethods] = &[ - new_generic(false, false), - new_generic(true, false), - new_generic(false, true), - new_generic(true, true), - ]; - - fn length(seq: &PySequence, vm: &VirtualMachine) -> PyResult { - length_wrapper(seq.obj, vm) - } - fn item(seq: &PySequence, i: isize, vm: &VirtualMachine) -> PyResult { - vm.call_special_method(seq.obj.to_owned(), identifier!(vm, __getitem__), (i,)) - } - fn ass_item( - seq: &PySequence, - i: isize, - value: Option, - vm: &VirtualMachine, - ) -> PyResult<()> { - match value { - Some(value) => vm - .call_special_method( - seq.obj.to_owned(), - identifier!(vm, __setitem__), - (i.to_pyobject(vm), value), - ) - .map(|_| Ok(()))?, - None => vm - .call_special_method( - seq.obj.to_owned(), - identifier!(vm, __delitem__), - (i.to_pyobject(vm),), - ) - .map(|_| Ok(()))?, - } - } - - const fn new_generic(has_length: bool, has_ass_item: bool) -> PySequenceMethods { - PySequenceMethods { - length: if has_length { Some(length) } else { None }, - item: Some(item), - ass_item: if has_ass_item { Some(ass_item) } else { None }, - ..PySequenceMethods::NOT_IMPLEMENTED - } - } - - let key = bool_int(has_length) | (bool_int(has_ass_item) << 1); - - &METHODS[key] + PyMappingMethods::generic(has_length, has_subscript, has_ass_subscript) } -fn as_sequence_generic(zelf: &PyObject, vm: &VirtualMachine) -> &'static PySequenceMethods { +fn slot_as_sequence(zelf: &PyObject, vm: &VirtualMachine) -> &'static PySequenceMethods { if !zelf.class().has_attr(identifier!(vm, __getitem__)) { return &PySequenceMethods::NOT_IMPLEMENTED; } @@ -336,69 +202,16 @@ fn as_sequence_generic(zelf: &PyObject, vm: &VirtualMachine) -> &'static PySeque zelf.class().has_attr(identifier!(vm, __setitem__)) | zelf.class().has_attr(identifier!(vm, __delitem__)), ); - - static_as_sequence_generic(has_length, has_ass_item) -} - -pub(crate) fn static_as_number_generic( - has_int: bool, - has_float: bool, - has_index: bool, -) -> &'static PyNumberMethods { - static METHODS: &[PyNumberMethods] = &[ - new_generic(false, false, false), - new_generic(true, false, false), - new_generic(false, true, false), - new_generic(true, true, false), - new_generic(false, false, true), - new_generic(true, false, true), - new_generic(false, true, true), - new_generic(true, true, true), - ]; - - fn int(num: &PyNumber, vm: &VirtualMachine) -> PyResult> { - let ret = vm.call_special_method(num.obj.to_owned(), identifier!(vm, __int__), ())?; - ret.downcast::().map_err(|obj| { - vm.new_type_error(format!("__int__ returned non-int (type {})", obj.class())) - }) - } - fn float(num: &PyNumber, vm: &VirtualMachine) -> PyResult> { - let ret = vm.call_special_method(num.obj.to_owned(), identifier!(vm, __float__), ())?; - ret.downcast::().map_err(|obj| { - vm.new_type_error(format!( - "__float__ returned non-float (type {})", - obj.class() - )) - }) - } - fn index(num: &PyNumber, vm: &VirtualMachine) -> PyResult> { - let ret = vm.call_special_method(num.obj.to_owned(), identifier!(vm, __index__), ())?; - ret.downcast::().map_err(|obj| { - vm.new_type_error(format!("__index__ returned non-int (type {})", obj.class())) - }) - } - - const fn new_generic(has_int: bool, has_float: bool, has_index: bool) -> PyNumberMethods { - PyNumberMethods { - int: if has_int { Some(int) } else { None }, - float: if has_float { Some(float) } else { None }, - index: if has_index { Some(index) } else { None }, - ..PyNumberMethods::NOT_IMPLEMENTED - } - } - - let key = bool_int(has_int) | (bool_int(has_float) << 1) | (bool_int(has_index) << 2); - - &METHODS[key] + PySequenceMethods::generic(has_length, has_ass_item) } -fn as_number_wrapper(zelf: &PyObject, vm: &VirtualMachine) -> &'static PyNumberMethods { +fn slot_as_number(zelf: &PyObject, vm: &VirtualMachine) -> &'static PyNumberMethods { let (has_int, has_float, has_index) = ( zelf.class().has_attr(identifier!(vm, __int__)), zelf.class().has_attr(identifier!(vm, __float__)), zelf.class().has_attr(identifier!(vm, __index__)), ); - static_as_number_generic(has_int, has_float, has_index) + PyNumberMethods::generic(has_int, has_float, has_index) } fn hash_wrapper(zelf: &PyObject, vm: &VirtualMachine) -> PyResult { @@ -513,8 +326,8 @@ impl PyType { } match name.as_str() { "__len__" | "__getitem__" | "__setitem__" | "__delitem__" => { - update_slot!(as_mapping, as_mapping_generic); - update_slot!(as_sequence, as_sequence_generic); + update_slot!(as_mapping, slot_as_mapping); + update_slot!(as_sequence, slot_as_sequence); } "__hash__" => { update_slot!(hash, hash_wrapper); @@ -553,7 +366,7 @@ impl PyType { update_slot!(del, del_wrapper); } "__int__" | "__index__" | "__float__" => { - update_slot!(as_number, as_number_wrapper); + update_slot!(as_number, slot_as_number); } _ => {} }