mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-29 11:14:38 +08:00
Use num_enum crate for oparg types (#6980)
* Use `num_enum` crate for oparg types * Fix doctest * Make opargs `#[repr(u8)]` * BuildSliceArgCount optimized
This commit is contained in:
1 parent
19db8d0b9f
commit
956f471013
4 files changed
+336
-336
No files matched your search
Generated
+1
@@ -3161,6 +3161,7 @@ dependencies = [
|
||||
"lz4_flex",
|
||||
"malachite-bigint",
|
||||
"num-complex",
|
||||
"num_enum",
|
||||
"ruff_source_file",
|
||||
"rustpython-wtf8",
|
||||
]
|
||||
|
||||
@@ -17,6 +17,7 @@ bitflags = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
malachite-bigint = { workspace = true }
|
||||
num-complex = { workspace = true }
|
||||
num_enum = { workspace = true }
|
||||
|
||||
lz4_flex = "0.12"
|
||||
|
||||
|
||||
@@ -1249,7 +1249,7 @@ impl<T: OpArgType> Arg<T> {
|
||||
|
||||
#[inline]
|
||||
pub fn new(arg: T) -> (Self, OpArg) {
|
||||
(Self(PhantomData), OpArg(arg.to_op_arg()))
|
||||
(Self(PhantomData), OpArg(arg.into()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -1267,7 +1267,7 @@ impl<T: OpArgType> Arg<T> {
|
||||
|
||||
#[inline(always)]
|
||||
pub fn try_get(self, arg: OpArg) -> Result<T, MarshalError> {
|
||||
T::from_op_arg(arg.0)
|
||||
T::try_from(arg.0).map_err(|_| MarshalError::InvalidBytecode)
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
@@ -1275,7 +1275,7 @@ impl<T: OpArgType> Arg<T> {
|
||||
#[inline(always)]
|
||||
pub unsafe fn get_unchecked(self, arg: OpArg) -> T {
|
||||
// SAFETY: requirements forwarded from caller
|
||||
unsafe { T::from_op_arg(arg.0).unwrap_unchecked() }
|
||||
unsafe { T::try_from(arg.0).unwrap_unchecked() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
use bitflags::bitflags;
|
||||
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||
|
||||
use core::{fmt, num::NonZeroU8};
|
||||
use core::fmt;
|
||||
|
||||
use crate::{
|
||||
bytecode::{CodeUnit, instruction::Instruction},
|
||||
marshal::MarshalError,
|
||||
};
|
||||
|
||||
pub trait OpArgType: Copy {
|
||||
fn from_op_arg(x: u32) -> Result<Self, MarshalError>;
|
||||
|
||||
fn to_op_arg(self) -> u32;
|
||||
}
|
||||
pub trait OpArgType: Copy + Into<u32> + TryFrom<u32> {}
|
||||
|
||||
/// Opcode argument that may be extended by a prior ExtendedArg.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
@@ -107,13 +104,34 @@ impl OpArgState {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_oparg_enum_traits {
|
||||
($name:ty) => {
|
||||
impl From<$name> for u32 {
|
||||
fn from(value: $name) -> Self {
|
||||
Self::from(u8::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u32> for $name {
|
||||
type Error = $crate::marshal::MarshalError;
|
||||
|
||||
fn try_from(value: u32) -> Result<Self, Self::Error> {
|
||||
u8::try_from(value)
|
||||
.map_err(|_| Self::Error::InvalidBytecode)
|
||||
.map(TryInto::try_into)?
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Oparg values for [`Instruction::ConvertValue`].
|
||||
///
|
||||
/// ## See also
|
||||
///
|
||||
/// - [CPython FVC_* flags](https://github.com/python/cpython/blob/8183fa5e3f78ca6ab862de7fb8b14f3d929421e0/Include/ceval.h#L129-L132)
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, IntoPrimitive, PartialEq, TryFromPrimitive)]
|
||||
#[num_enum(error_type(name = MarshalError, constructor = new_invalid_bytecode))]
|
||||
pub enum ConvertValueOparg {
|
||||
/// No conversion.
|
||||
///
|
||||
@@ -121,6 +139,8 @@ pub enum ConvertValueOparg {
|
||||
/// f"{x}"
|
||||
/// f"{x:4}"
|
||||
/// ```
|
||||
// Ruff `ConversionFlag::None` is `-1i8`, when its converted to `u8` its value is `u8::MAX`.
|
||||
#[num_enum(alternatives = [255])]
|
||||
None = 0,
|
||||
/// Converts by calling `str(<value>)`.
|
||||
///
|
||||
@@ -145,6 +165,8 @@ pub enum ConvertValueOparg {
|
||||
Ascii = 3,
|
||||
}
|
||||
|
||||
impl_oparg_enum_traits!(ConvertValueOparg);
|
||||
|
||||
impl fmt::Display for ConvertValueOparg {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let out = match self {
|
||||
@@ -159,29 +181,12 @@ impl fmt::Display for ConvertValueOparg {
|
||||
}
|
||||
}
|
||||
|
||||
impl OpArgType for ConvertValueOparg {
|
||||
#[inline]
|
||||
fn from_op_arg(x: u32) -> Result<Self, MarshalError> {
|
||||
Ok(match x {
|
||||
// Ruff `ConversionFlag::None` is `-1i8`,
|
||||
// when its converted to `u8` its value is `u8::MAX`
|
||||
0 | 255 => Self::None,
|
||||
1 => Self::Str,
|
||||
2 => Self::Repr,
|
||||
3 => Self::Ascii,
|
||||
_ => return Err(MarshalError::InvalidBytecode),
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_op_arg(self) -> u32 {
|
||||
self as u32
|
||||
}
|
||||
}
|
||||
impl OpArgType for ConvertValueOparg {}
|
||||
|
||||
/// Resume type for the RESUME instruction
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
#[repr(u32)]
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, IntoPrimitive, TryFromPrimitive)]
|
||||
#[num_enum(error_type(name = MarshalError, constructor = new_invalid_bytecode))]
|
||||
pub enum ResumeType {
|
||||
AtFuncStart = 0,
|
||||
AfterYield = 1,
|
||||
@@ -189,145 +194,108 @@ pub enum ResumeType {
|
||||
AfterAwait = 3,
|
||||
}
|
||||
|
||||
impl OpArgType for u32 {
|
||||
#[inline(always)]
|
||||
fn from_op_arg(x: u32) -> Result<Self, MarshalError> {
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn to_op_arg(self) -> u32 {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl OpArgType for bool {
|
||||
#[inline(always)]
|
||||
fn from_op_arg(x: u32) -> Result<Self, MarshalError> {
|
||||
Ok(x != 0)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn to_op_arg(self) -> u32 {
|
||||
self as u32
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! op_arg_enum_impl {
|
||||
(enum $name:ident { $($(#[$var_attr:meta])* $var:ident = $value:literal,)* }) => {
|
||||
impl OpArgType for $name {
|
||||
fn to_op_arg(self) -> u32 {
|
||||
self as u32
|
||||
}
|
||||
|
||||
fn from_op_arg(x: u32) -> Result<Self, MarshalError> {
|
||||
Ok(match u8::try_from(x).map_err(|_| MarshalError::InvalidBytecode)? {
|
||||
$($value => Self::$var,)*
|
||||
_ => return Err(MarshalError::InvalidBytecode),
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! op_arg_enum {
|
||||
($(#[$attr:meta])* $vis:vis enum $name:ident { $($(#[$var_attr:meta])* $var:ident = $value:literal,)* }) => {
|
||||
$(#[$attr])*
|
||||
$vis enum $name {
|
||||
$($(#[$var_attr])* $var = $value,)*
|
||||
}
|
||||
|
||||
op_arg_enum_impl!(enum $name {
|
||||
$($(#[$var_attr])* $var = $value,)*
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
pub type NameIdx = u32;
|
||||
|
||||
impl OpArgType for u32 {}
|
||||
//impl OpArgType for bool {}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||
#[repr(transparent)]
|
||||
pub struct Label(pub u32);
|
||||
|
||||
impl OpArgType for Label {
|
||||
#[inline(always)]
|
||||
fn from_op_arg(x: u32) -> Result<Self, MarshalError> {
|
||||
Ok(Self(x))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn to_op_arg(self) -> u32 {
|
||||
self.0
|
||||
impl Label {
|
||||
pub const fn new(value: u32) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Label {
|
||||
fn from(value: u32) -> Self {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Label> for u32 {
|
||||
fn from(value: Label) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl OpArgType for Label {}
|
||||
|
||||
impl fmt::Display for Label {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
op_arg_enum!(
|
||||
/// The kind of Raise that occurred.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum RaiseKind {
|
||||
/// Bare `raise` statement with no arguments.
|
||||
/// Gets the current exception from VM state (topmost_exception).
|
||||
/// Maps to RAISE_VARARGS with oparg=0.
|
||||
BareRaise = 0,
|
||||
/// `raise exc` - exception is on the stack.
|
||||
/// Maps to RAISE_VARARGS with oparg=1.
|
||||
Raise = 1,
|
||||
/// `raise exc from cause` - exception and cause are on the stack.
|
||||
/// Maps to RAISE_VARARGS with oparg=2.
|
||||
RaiseCause = 2,
|
||||
/// Reraise exception from the stack top.
|
||||
/// Used in exception handler cleanup blocks (finally, except).
|
||||
/// Gets exception from stack, not from VM state.
|
||||
/// Maps to the RERAISE opcode.
|
||||
ReraiseFromStack = 3,
|
||||
}
|
||||
);
|
||||
/// The kind of Raise that occurred.
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, TryFromPrimitive, IntoPrimitive, Eq)]
|
||||
#[num_enum(error_type(name = MarshalError, constructor = new_invalid_bytecode))]
|
||||
pub enum RaiseKind {
|
||||
/// Bare `raise` statement with no arguments.
|
||||
/// Gets the current exception from VM state (topmost_exception).
|
||||
/// Maps to RAISE_VARARGS with oparg=0.
|
||||
BareRaise = 0,
|
||||
/// `raise exc` - exception is on the stack.
|
||||
/// Maps to RAISE_VARARGS with oparg=1.
|
||||
Raise = 1,
|
||||
/// `raise exc from cause` - exception and cause are on the stack.
|
||||
/// Maps to RAISE_VARARGS with oparg=2.
|
||||
RaiseCause = 2,
|
||||
/// Reraise exception from the stack top.
|
||||
/// Used in exception handler cleanup blocks (finally, except).
|
||||
/// Gets exception from stack, not from VM state.
|
||||
/// Maps to the RERAISE opcode.
|
||||
ReraiseFromStack = 3,
|
||||
}
|
||||
|
||||
op_arg_enum!(
|
||||
/// Intrinsic function for CALL_INTRINSIC_1
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum IntrinsicFunction1 {
|
||||
// Invalid = 0,
|
||||
Print = 1,
|
||||
/// Import * operation
|
||||
ImportStar = 2,
|
||||
/// Convert StopIteration to RuntimeError in async context
|
||||
StopIterationError = 3,
|
||||
AsyncGenWrap = 4,
|
||||
UnaryPositive = 5,
|
||||
/// Convert list to tuple
|
||||
ListToTuple = 6,
|
||||
/// Type parameter related
|
||||
TypeVar = 7,
|
||||
ParamSpec = 8,
|
||||
TypeVarTuple = 9,
|
||||
/// Generic subscript for PEP 695
|
||||
SubscriptGeneric = 10,
|
||||
TypeAlias = 11,
|
||||
}
|
||||
);
|
||||
impl_oparg_enum_traits!(RaiseKind);
|
||||
impl OpArgType for RaiseKind {}
|
||||
|
||||
op_arg_enum!(
|
||||
/// Intrinsic function for CALL_INTRINSIC_2
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum IntrinsicFunction2 {
|
||||
PrepReraiseStar = 1,
|
||||
TypeVarWithBound = 2,
|
||||
TypeVarWithConstraint = 3,
|
||||
SetFunctionTypeParams = 4,
|
||||
/// Set default value for type parameter (PEP 695)
|
||||
SetTypeparamDefault = 5,
|
||||
}
|
||||
);
|
||||
/// Intrinsic function for CALL_INTRINSIC_1
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, IntoPrimitive, TryFromPrimitive)]
|
||||
#[num_enum(error_type(name = MarshalError, constructor = new_invalid_bytecode))]
|
||||
pub enum IntrinsicFunction1 {
|
||||
// Invalid = 0,
|
||||
Print = 1,
|
||||
/// Import * operation
|
||||
ImportStar = 2,
|
||||
/// Convert StopIteration to RuntimeError in async context
|
||||
StopIterationError = 3,
|
||||
AsyncGenWrap = 4,
|
||||
UnaryPositive = 5,
|
||||
/// Convert list to tuple
|
||||
ListToTuple = 6,
|
||||
/// Type parameter related
|
||||
TypeVar = 7,
|
||||
ParamSpec = 8,
|
||||
TypeVarTuple = 9,
|
||||
/// Generic subscript for PEP 695
|
||||
SubscriptGeneric = 10,
|
||||
TypeAlias = 11,
|
||||
}
|
||||
|
||||
impl_oparg_enum_traits!(IntrinsicFunction1);
|
||||
impl OpArgType for IntrinsicFunction1 {}
|
||||
|
||||
/// Intrinsic function for CALL_INTRINSIC_2
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
|
||||
#[num_enum(error_type(name = MarshalError, constructor = new_invalid_bytecode))]
|
||||
pub enum IntrinsicFunction2 {
|
||||
PrepReraiseStar = 1,
|
||||
TypeVarWithBound = 2,
|
||||
TypeVarWithConstraint = 3,
|
||||
SetFunctionTypeParams = 4,
|
||||
/// Set default value for type parameter (PEP 695)
|
||||
SetTypeparamDefault = 5,
|
||||
}
|
||||
|
||||
impl_oparg_enum_traits!(IntrinsicFunction2);
|
||||
impl OpArgType for IntrinsicFunction2 {}
|
||||
|
||||
bitflags! {
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
@@ -342,106 +310,111 @@ bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
impl OpArgType for MakeFunctionFlags {
|
||||
#[inline(always)]
|
||||
fn from_op_arg(x: u32) -> Result<Self, MarshalError> {
|
||||
Self::from_bits(x as u8).ok_or(MarshalError::InvalidBytecode)
|
||||
}
|
||||
impl TryFrom<u32> for MakeFunctionFlags {
|
||||
type Error = MarshalError;
|
||||
|
||||
#[inline(always)]
|
||||
fn to_op_arg(self) -> u32 {
|
||||
self.bits().into()
|
||||
fn try_from(value: u32) -> Result<Self, Self::Error> {
|
||||
Self::from_bits(value as u8).ok_or(Self::Error::InvalidBytecode)
|
||||
}
|
||||
}
|
||||
|
||||
op_arg_enum!(
|
||||
/// The possible comparison operators
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum ComparisonOperator {
|
||||
// be intentional with bits so that we can do eval_ord with just a bitwise and
|
||||
// bits: | Equal | Greater | Less |
|
||||
Less = 0b001,
|
||||
Greater = 0b010,
|
||||
NotEqual = 0b011,
|
||||
Equal = 0b100,
|
||||
LessOrEqual = 0b101,
|
||||
GreaterOrEqual = 0b110,
|
||||
impl From<MakeFunctionFlags> for u32 {
|
||||
fn from(value: MakeFunctionFlags) -> Self {
|
||||
value.bits().into()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
op_arg_enum!(
|
||||
/// The possible Binary operators
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use rustpython_compiler_core::bytecode::{Arg, BinaryOperator, Instruction};
|
||||
/// let (op, _) = Arg::new(BinaryOperator::Add);
|
||||
/// let instruction = Instruction::BinaryOp { op };
|
||||
/// ```
|
||||
///
|
||||
/// See also:
|
||||
/// - [_PyEval_BinaryOps](https://github.com/python/cpython/blob/8183fa5e3f78ca6ab862de7fb8b14f3d929421e0/Python/ceval.c#L316-L343)
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum BinaryOperator {
|
||||
/// `+`
|
||||
Add = 0,
|
||||
/// `&`
|
||||
And = 1,
|
||||
/// `//`
|
||||
FloorDivide = 2,
|
||||
/// `<<`
|
||||
Lshift = 3,
|
||||
/// `@`
|
||||
MatrixMultiply = 4,
|
||||
/// `*`
|
||||
Multiply = 5,
|
||||
/// `%`
|
||||
Remainder = 6,
|
||||
/// `|`
|
||||
Or = 7,
|
||||
/// `**`
|
||||
Power = 8,
|
||||
/// `>>`
|
||||
Rshift = 9,
|
||||
/// `-`
|
||||
Subtract = 10,
|
||||
/// `/`
|
||||
TrueDivide = 11,
|
||||
/// `^`
|
||||
Xor = 12,
|
||||
/// `+=`
|
||||
InplaceAdd = 13,
|
||||
/// `&=`
|
||||
InplaceAnd = 14,
|
||||
/// `//=`
|
||||
InplaceFloorDivide = 15,
|
||||
/// `<<=`
|
||||
InplaceLshift = 16,
|
||||
/// `@=`
|
||||
InplaceMatrixMultiply = 17,
|
||||
/// `*=`
|
||||
InplaceMultiply = 18,
|
||||
/// `%=`
|
||||
InplaceRemainder = 19,
|
||||
/// `|=`
|
||||
InplaceOr = 20,
|
||||
/// `**=`
|
||||
InplacePower = 21,
|
||||
/// `>>=`
|
||||
InplaceRshift = 22,
|
||||
/// `-=`
|
||||
InplaceSubtract = 23,
|
||||
/// `/=`
|
||||
InplaceTrueDivide = 24,
|
||||
/// `^=`
|
||||
InplaceXor = 25,
|
||||
/// `[]` subscript
|
||||
Subscr = 26,
|
||||
}
|
||||
);
|
||||
impl OpArgType for MakeFunctionFlags {}
|
||||
|
||||
/// The possible comparison operators.
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
|
||||
#[num_enum(error_type(name = MarshalError, constructor = new_invalid_bytecode))]
|
||||
pub enum ComparisonOperator {
|
||||
// be intentional with bits so that we can do eval_ord with just a bitwise and
|
||||
// bits: | Equal | Greater | Less |
|
||||
Less = 0b001,
|
||||
Greater = 0b010,
|
||||
NotEqual = 0b011,
|
||||
Equal = 0b100,
|
||||
LessOrEqual = 0b101,
|
||||
GreaterOrEqual = 0b110,
|
||||
}
|
||||
|
||||
impl_oparg_enum_traits!(ComparisonOperator);
|
||||
impl OpArgType for ComparisonOperator {}
|
||||
|
||||
/// The possible Binary operators
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use rustpython_compiler_core::bytecode::{Arg, BinaryOperator, Instruction};
|
||||
/// let (op, _) = Arg::new(BinaryOperator::Add);
|
||||
/// let instruction = Instruction::BinaryOp { op };
|
||||
/// ```
|
||||
///
|
||||
/// See also:
|
||||
/// - [_PyEval_BinaryOps](https://github.com/python/cpython/blob/8183fa5e3f78ca6ab862de7fb8b14f3d929421e0/Python/ceval.c#L316-L343)
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
|
||||
#[num_enum(error_type(name = MarshalError, constructor = new_invalid_bytecode))]
|
||||
pub enum BinaryOperator {
|
||||
/// `+`
|
||||
Add = 0,
|
||||
/// `&`
|
||||
And = 1,
|
||||
/// `//`
|
||||
FloorDivide = 2,
|
||||
/// `<<`
|
||||
Lshift = 3,
|
||||
/// `@`
|
||||
MatrixMultiply = 4,
|
||||
/// `*`
|
||||
Multiply = 5,
|
||||
/// `%`
|
||||
Remainder = 6,
|
||||
/// `|`
|
||||
Or = 7,
|
||||
/// `**`
|
||||
Power = 8,
|
||||
/// `>>`
|
||||
Rshift = 9,
|
||||
/// `-`
|
||||
Subtract = 10,
|
||||
/// `/`
|
||||
TrueDivide = 11,
|
||||
/// `^`
|
||||
Xor = 12,
|
||||
/// `+=`
|
||||
InplaceAdd = 13,
|
||||
/// `&=`
|
||||
InplaceAnd = 14,
|
||||
/// `//=`
|
||||
InplaceFloorDivide = 15,
|
||||
/// `<<=`
|
||||
InplaceLshift = 16,
|
||||
/// `@=`
|
||||
InplaceMatrixMultiply = 17,
|
||||
/// `*=`
|
||||
InplaceMultiply = 18,
|
||||
/// `%=`
|
||||
InplaceRemainder = 19,
|
||||
/// `|=`
|
||||
InplaceOr = 20,
|
||||
/// `**=`
|
||||
InplacePower = 21,
|
||||
/// `>>=`
|
||||
InplaceRshift = 22,
|
||||
/// `-=`
|
||||
InplaceSubtract = 23,
|
||||
/// `/=`
|
||||
InplaceTrueDivide = 24,
|
||||
/// `^=`
|
||||
InplaceXor = 25,
|
||||
/// `[]` subscript
|
||||
Subscr = 26,
|
||||
}
|
||||
|
||||
impl BinaryOperator {
|
||||
/// Get the "inplace" version of the operator.
|
||||
@@ -476,6 +449,9 @@ impl BinaryOperator {
|
||||
}
|
||||
}
|
||||
|
||||
impl_oparg_enum_traits!(BinaryOperator);
|
||||
impl OpArgType for BinaryOperator {}
|
||||
|
||||
impl fmt::Display for BinaryOperator {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let op = match self {
|
||||
@@ -511,39 +487,43 @@ impl fmt::Display for BinaryOperator {
|
||||
}
|
||||
}
|
||||
|
||||
op_arg_enum!(
|
||||
/// Whether or not to invert the operation.
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Invert {
|
||||
/// ```py
|
||||
/// foo is bar
|
||||
/// x in lst
|
||||
/// ```
|
||||
No = 0,
|
||||
/// ```py
|
||||
/// foo is not bar
|
||||
/// x not in lst
|
||||
/// ```
|
||||
Yes = 1,
|
||||
}
|
||||
);
|
||||
/// Whether or not to invert the operation.
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
|
||||
#[num_enum(error_type(name = MarshalError, constructor = new_invalid_bytecode))]
|
||||
pub enum Invert {
|
||||
/// ```py
|
||||
/// foo is bar
|
||||
/// x in lst
|
||||
/// ```
|
||||
No = 0,
|
||||
/// ```py
|
||||
/// foo is not bar
|
||||
/// x not in lst
|
||||
/// ```
|
||||
Yes = 1,
|
||||
}
|
||||
|
||||
op_arg_enum!(
|
||||
/// Special method for LOAD_SPECIAL opcode (context managers).
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum SpecialMethod {
|
||||
/// `__enter__` for sync context manager
|
||||
Enter = 0,
|
||||
/// `__exit__` for sync context manager
|
||||
Exit = 1,
|
||||
/// `__aenter__` for async context manager
|
||||
AEnter = 2,
|
||||
/// `__aexit__` for async context manager
|
||||
AExit = 3,
|
||||
}
|
||||
);
|
||||
impl_oparg_enum_traits!(Invert);
|
||||
impl OpArgType for Invert {}
|
||||
|
||||
/// Special method for LOAD_SPECIAL opcode (context managers).
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
|
||||
#[num_enum(error_type(name = MarshalError, constructor = new_invalid_bytecode))]
|
||||
pub enum SpecialMethod {
|
||||
/// `__enter__` for sync context manager
|
||||
Enter = 0,
|
||||
/// `__exit__` for sync context manager
|
||||
Exit = 1,
|
||||
/// `__aenter__` for async context manager
|
||||
AEnter = 2,
|
||||
/// `__aexit__` for async context manager
|
||||
AExit = 3,
|
||||
}
|
||||
|
||||
impl_oparg_enum_traits!(SpecialMethod);
|
||||
impl OpArgType for SpecialMethod {}
|
||||
|
||||
impl fmt::Display for SpecialMethod {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
@@ -557,24 +537,26 @@ impl fmt::Display for SpecialMethod {
|
||||
}
|
||||
}
|
||||
|
||||
op_arg_enum!(
|
||||
/// Common constants for LOAD_COMMON_CONSTANT opcode.
|
||||
/// pycore_opcode_utils.h CONSTANT_*
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum CommonConstant {
|
||||
/// `AssertionError` exception type
|
||||
AssertionError = 0,
|
||||
/// `NotImplementedError` exception type
|
||||
NotImplementedError = 1,
|
||||
/// Built-in `tuple` type
|
||||
BuiltinTuple = 2,
|
||||
/// Built-in `all` function
|
||||
BuiltinAll = 3,
|
||||
/// Built-in `any` function
|
||||
BuiltinAny = 4,
|
||||
}
|
||||
);
|
||||
/// Common constants for LOAD_COMMON_CONSTANT opcode.
|
||||
/// pycore_opcode_utils.h CONSTANT_*
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
|
||||
#[num_enum(error_type(name = MarshalError, constructor = new_invalid_bytecode))]
|
||||
pub enum CommonConstant {
|
||||
/// `AssertionError` exception type
|
||||
AssertionError = 0,
|
||||
/// `NotImplementedError` exception type
|
||||
NotImplementedError = 1,
|
||||
/// Built-in `tuple` type
|
||||
BuiltinTuple = 2,
|
||||
/// Built-in `all` function
|
||||
BuiltinAll = 3,
|
||||
/// Built-in `any` function
|
||||
BuiltinAny = 4,
|
||||
}
|
||||
|
||||
impl_oparg_enum_traits!(CommonConstant);
|
||||
impl OpArgType for CommonConstant {}
|
||||
|
||||
impl fmt::Display for CommonConstant {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
@@ -602,54 +584,60 @@ pub enum BuildSliceArgCount {
|
||||
Three,
|
||||
}
|
||||
|
||||
impl OpArgType for BuildSliceArgCount {
|
||||
#[inline(always)]
|
||||
fn from_op_arg(x: u32) -> Result<Self, MarshalError> {
|
||||
Ok(match x {
|
||||
impl TryFrom<u8> for BuildSliceArgCount {
|
||||
type Error = MarshalError;
|
||||
|
||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||
Ok(match value {
|
||||
2 => Self::Two,
|
||||
3 => Self::Three,
|
||||
_ => return Err(MarshalError::InvalidBytecode),
|
||||
_ => return Err(Self::Error::InvalidBytecode),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn to_op_arg(self) -> u32 {
|
||||
u32::from(self.argc().get())
|
||||
impl TryFrom<u32> for BuildSliceArgCount {
|
||||
type Error = MarshalError;
|
||||
|
||||
fn try_from(value: u32) -> Result<Self, Self::Error> {
|
||||
u8::try_from(value)
|
||||
.map_err(|_| Self::Error::InvalidBytecode)
|
||||
.map(TryInto::try_into)?
|
||||
}
|
||||
}
|
||||
|
||||
impl BuildSliceArgCount {
|
||||
/// Get the numeric value of `Self`.
|
||||
#[must_use]
|
||||
pub const fn argc(self) -> NonZeroU8 {
|
||||
let inner = match self {
|
||||
Self::Two => 2,
|
||||
Self::Three => 3,
|
||||
};
|
||||
// Safety: `inner` can be either 2 or 3.
|
||||
unsafe { NonZeroU8::new_unchecked(inner) }
|
||||
impl From<BuildSliceArgCount> for u32 {
|
||||
fn from(value: BuildSliceArgCount) -> Self {
|
||||
match value {
|
||||
BuildSliceArgCount::Two => 2,
|
||||
BuildSliceArgCount::Three => 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OpArgType for BuildSliceArgCount {}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct UnpackExArgs {
|
||||
pub before: u8,
|
||||
pub after: u8,
|
||||
}
|
||||
|
||||
impl OpArgType for UnpackExArgs {
|
||||
#[inline(always)]
|
||||
fn from_op_arg(x: u32) -> Result<Self, MarshalError> {
|
||||
let [before, after, ..] = x.to_le_bytes();
|
||||
Ok(Self { before, after })
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn to_op_arg(self) -> u32 {
|
||||
u32::from_le_bytes([self.before, self.after, 0, 0])
|
||||
impl From<u32> for UnpackExArgs {
|
||||
fn from(value: u32) -> Self {
|
||||
let [before, after, ..] = value.to_le_bytes();
|
||||
Self { before, after }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UnpackExArgs> for u32 {
|
||||
fn from(value: UnpackExArgs) -> Self {
|
||||
Self::from_le_bytes([value.before, value.after, 0, 0])
|
||||
}
|
||||
}
|
||||
|
||||
impl OpArgType for UnpackExArgs {}
|
||||
|
||||
impl fmt::Display for UnpackExArgs {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "before: {}, after: {}", self.before, self.after)
|
||||
@@ -686,17 +674,7 @@ impl LoadSuperAttr {
|
||||
}
|
||||
}
|
||||
|
||||
impl OpArgType for LoadSuperAttr {
|
||||
#[inline(always)]
|
||||
fn from_op_arg(x: u32) -> Result<Self, MarshalError> {
|
||||
Ok(x.into())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn to_op_arg(self) -> u32 {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
impl OpArgType for LoadSuperAttr {}
|
||||
|
||||
impl From<u32> for LoadSuperAttr {
|
||||
fn from(value: u32) -> Self {
|
||||
@@ -749,3 +727,23 @@ impl From<LoadSuperAttrBuilder> for LoadSuperAttr {
|
||||
builder.build()
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function for `num_enum` derive macro.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use num_enum::TryFromPrimitive;
|
||||
///
|
||||
/// use rustpython_compiler_core::marshal::MarshalError;
|
||||
///
|
||||
/// #[repr(u8)]
|
||||
/// #[derive(TryFromPrimitive)]
|
||||
/// #[num_enum(error_type(name = MarshalError, constructor = new_invalid_bytecode))]
|
||||
/// enum Foo {
|
||||
/// A = 1,
|
||||
/// B = 2
|
||||
/// }
|
||||
fn new_invalid_bytecode<T>(_: T) -> MarshalError {
|
||||
MarshalError::InvalidBytecode
|
||||
}
|
||||
Reference in new issue
Block a user