mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Adapt bitflagset to use enum (#7419)
This commit is contained in:
1 parent
7e2154f382
commit
13a0623eb1
11 files changed
+193
-154
No files matched your search
@@ -5,6 +5,7 @@ biguint
|
||||
bindgen
|
||||
bitand
|
||||
bitflags
|
||||
bitflagset
|
||||
bitor
|
||||
bitvec
|
||||
bitxor
|
||||
|
||||
Generated
+33
@@ -349,6 +349,18 @@ version = "2.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
||||
|
||||
[[package]]
|
||||
name = "bitflagset"
|
||||
version = "0.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64b6ee310aa7af14142c8c9121775774ff601ae055ed98ba7fac96098bcde1b9"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"radium",
|
||||
"ref-cast",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blake2"
|
||||
version = "0.10.6"
|
||||
@@ -2769,6 +2781,26 @@ dependencies = [
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ref-cast"
|
||||
version = "1.0.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d"
|
||||
dependencies = [
|
||||
"ref-cast-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ref-cast-impl"
|
||||
version = "1.0.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regalloc2"
|
||||
version = "0.13.5"
|
||||
@@ -3128,6 +3160,7 @@ name = "rustpython-compiler-core"
|
||||
version = "0.4.0"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"bitflagset",
|
||||
"itertools 0.14.0",
|
||||
"lz4_flex",
|
||||
"malachite-bigint",
|
||||
|
||||
@@ -167,6 +167,7 @@ phf = { version = "0.13.1", default-features = false, features = ["macros"]}
|
||||
ahash = "0.8.12"
|
||||
ascii = "1.1"
|
||||
bitflags = "2.11.0"
|
||||
bitflagset = "0.0.3"
|
||||
bstr = "1"
|
||||
bytes = "1.11.1"
|
||||
cfg-if = "1.0"
|
||||
|
||||
@@ -2509,7 +2509,7 @@ impl Compiler {
|
||||
self.compile_expression(value)?;
|
||||
emit!(self, Instruction::ReturnValue);
|
||||
let value_code = self.exit_scope();
|
||||
self.make_closure(value_code, bytecode::MakeFunctionFlags::empty())?;
|
||||
self.make_closure(value_code, bytecode::MakeFunctionFlags::new())?;
|
||||
// Stack: [type_params_tuple, value_closure]
|
||||
|
||||
// Swap so unpack_sequence reverse gives correct order
|
||||
@@ -2522,7 +2522,7 @@ impl Compiler {
|
||||
|
||||
let code = self.exit_scope();
|
||||
self.ctx = prev_ctx;
|
||||
self.make_closure(code, bytecode::MakeFunctionFlags::empty())?;
|
||||
self.make_closure(code, bytecode::MakeFunctionFlags::new())?;
|
||||
emit!(self, Instruction::PushNull);
|
||||
emit!(self, Instruction::Call { argc: 0 });
|
||||
|
||||
@@ -2561,7 +2561,7 @@ impl Compiler {
|
||||
|
||||
let code = self.exit_scope();
|
||||
self.ctx = prev_ctx;
|
||||
self.make_closure(code, bytecode::MakeFunctionFlags::empty())?;
|
||||
self.make_closure(code, bytecode::MakeFunctionFlags::new())?;
|
||||
// Stack: [name, None, closure]
|
||||
}
|
||||
|
||||
@@ -2725,7 +2725,7 @@ impl Compiler {
|
||||
self.ctx = prev_ctx;
|
||||
|
||||
// Create closure for lazy evaluation
|
||||
self.make_closure(code, bytecode::MakeFunctionFlags::empty())?;
|
||||
self.make_closure(code, bytecode::MakeFunctionFlags::new())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -3649,7 +3649,7 @@ impl Compiler {
|
||||
&mut self,
|
||||
parameters: &ast::Parameters,
|
||||
) -> CompileResult<bytecode::MakeFunctionFlags> {
|
||||
let mut funcflags = bytecode::MakeFunctionFlags::empty();
|
||||
let mut funcflags = bytecode::MakeFunctionFlags::new();
|
||||
|
||||
// Handle positional defaults
|
||||
let defaults: Vec<_> = core::iter::empty()
|
||||
@@ -3669,7 +3669,7 @@ impl Compiler {
|
||||
count: defaults.len().to_u32()
|
||||
}
|
||||
);
|
||||
funcflags |= bytecode::MakeFunctionFlags::DEFAULTS;
|
||||
funcflags.insert(bytecode::MakeFunctionFlag::Defaults);
|
||||
}
|
||||
|
||||
// Handle keyword-only defaults
|
||||
@@ -3694,7 +3694,7 @@ impl Compiler {
|
||||
count: kw_with_defaults.len().to_u32(),
|
||||
}
|
||||
);
|
||||
funcflags |= bytecode::MakeFunctionFlags::KW_ONLY_DEFAULTS;
|
||||
funcflags.insert(bytecode::MakeFunctionFlag::KwOnlyDefaults);
|
||||
}
|
||||
|
||||
Ok(funcflags)
|
||||
@@ -3844,7 +3844,7 @@ impl Compiler {
|
||||
let annotate_code = self.exit_annotation_scope(saved_ctx);
|
||||
|
||||
// Make a closure from the code object
|
||||
self.make_closure(annotate_code, bytecode::MakeFunctionFlags::empty())?;
|
||||
self.make_closure(annotate_code, bytecode::MakeFunctionFlags::new())?;
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
@@ -4054,7 +4054,7 @@ impl Compiler {
|
||||
);
|
||||
|
||||
// Make a closure from the code object
|
||||
self.make_closure(annotate_code, bytecode::MakeFunctionFlags::empty())?;
|
||||
self.make_closure(annotate_code, bytecode::MakeFunctionFlags::new())?;
|
||||
|
||||
// Store as __annotate_func__ for classes, __annotate__ for modules
|
||||
let name = if parent_scope_type == CompilerScope::Class {
|
||||
@@ -4092,10 +4092,10 @@ impl Compiler {
|
||||
|
||||
if is_generic {
|
||||
// Count args to pass to type params scope
|
||||
if funcflags.contains(bytecode::MakeFunctionFlags::DEFAULTS) {
|
||||
if funcflags.contains(&bytecode::MakeFunctionFlag::Defaults) {
|
||||
num_typeparam_args += 1;
|
||||
}
|
||||
if funcflags.contains(bytecode::MakeFunctionFlags::KW_ONLY_DEFAULTS) {
|
||||
if funcflags.contains(&bytecode::MakeFunctionFlag::KwOnlyDefaults) {
|
||||
num_typeparam_args += 1;
|
||||
}
|
||||
|
||||
@@ -4120,13 +4120,13 @@ impl Compiler {
|
||||
// Add parameter names to varnames for the type params scope
|
||||
// These will be passed as arguments when the closure is called
|
||||
let current_info = self.current_code_info();
|
||||
if funcflags.contains(bytecode::MakeFunctionFlags::DEFAULTS) {
|
||||
if funcflags.contains(&bytecode::MakeFunctionFlag::Defaults) {
|
||||
current_info
|
||||
.metadata
|
||||
.varnames
|
||||
.insert(".defaults".to_owned());
|
||||
}
|
||||
if funcflags.contains(bytecode::MakeFunctionFlags::KW_ONLY_DEFAULTS) {
|
||||
if funcflags.contains(&bytecode::MakeFunctionFlag::KwOnlyDefaults) {
|
||||
current_info
|
||||
.metadata
|
||||
.varnames
|
||||
@@ -4144,11 +4144,10 @@ impl Compiler {
|
||||
}
|
||||
|
||||
// Compile annotations as closure (PEP 649)
|
||||
let annotations_flag = if self.compile_annotations_closure(name, parameters, returns)? {
|
||||
bytecode::MakeFunctionFlags::ANNOTATE
|
||||
} else {
|
||||
bytecode::MakeFunctionFlags::empty()
|
||||
};
|
||||
let mut annotations_flag = bytecode::MakeFunctionFlags::new();
|
||||
if self.compile_annotations_closure(name, parameters, returns)? {
|
||||
annotations_flag.insert(bytecode::MakeFunctionFlag::Annotate);
|
||||
}
|
||||
|
||||
// Compile function body
|
||||
let final_funcflags = funcflags | annotations_flag;
|
||||
@@ -4179,7 +4178,7 @@ impl Compiler {
|
||||
self.ctx = saved_ctx;
|
||||
|
||||
// Make closure for type params code
|
||||
self.make_closure(type_params_code, bytecode::MakeFunctionFlags::empty())?;
|
||||
self.make_closure(type_params_code, bytecode::MakeFunctionFlags::new())?;
|
||||
|
||||
// Call the type params closure with defaults/kwdefaults as arguments.
|
||||
// Call protocol: [callable, self_or_null, arg1, ..., argN]
|
||||
@@ -4347,57 +4346,57 @@ impl Compiler {
|
||||
emit!(
|
||||
self,
|
||||
Instruction::SetFunctionAttribute {
|
||||
flag: bytecode::MakeFunctionFlags::CLOSURE
|
||||
flag: bytecode::MakeFunctionFlag::Closure
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Set annotations if present
|
||||
if flags.contains(bytecode::MakeFunctionFlags::ANNOTATIONS) {
|
||||
if flags.contains(&bytecode::MakeFunctionFlag::Annotations) {
|
||||
emit!(
|
||||
self,
|
||||
Instruction::SetFunctionAttribute {
|
||||
flag: bytecode::MakeFunctionFlags::ANNOTATIONS
|
||||
flag: bytecode::MakeFunctionFlag::Annotations
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Set __annotate__ closure if present (PEP 649)
|
||||
if flags.contains(bytecode::MakeFunctionFlags::ANNOTATE) {
|
||||
if flags.contains(&bytecode::MakeFunctionFlag::Annotate) {
|
||||
emit!(
|
||||
self,
|
||||
Instruction::SetFunctionAttribute {
|
||||
flag: bytecode::MakeFunctionFlags::ANNOTATE
|
||||
flag: bytecode::MakeFunctionFlag::Annotate
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Set kwdefaults if present
|
||||
if flags.contains(bytecode::MakeFunctionFlags::KW_ONLY_DEFAULTS) {
|
||||
if flags.contains(&bytecode::MakeFunctionFlag::KwOnlyDefaults) {
|
||||
emit!(
|
||||
self,
|
||||
Instruction::SetFunctionAttribute {
|
||||
flag: bytecode::MakeFunctionFlags::KW_ONLY_DEFAULTS
|
||||
flag: bytecode::MakeFunctionFlag::KwOnlyDefaults
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Set defaults if present
|
||||
if flags.contains(bytecode::MakeFunctionFlags::DEFAULTS) {
|
||||
if flags.contains(&bytecode::MakeFunctionFlag::Defaults) {
|
||||
emit!(
|
||||
self,
|
||||
Instruction::SetFunctionAttribute {
|
||||
flag: bytecode::MakeFunctionFlags::DEFAULTS
|
||||
flag: bytecode::MakeFunctionFlag::Defaults
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Set type_params if present
|
||||
if flags.contains(bytecode::MakeFunctionFlags::TYPE_PARAMS) {
|
||||
if flags.contains(&bytecode::MakeFunctionFlag::TypeParams) {
|
||||
emit!(
|
||||
self,
|
||||
Instruction::SetFunctionAttribute {
|
||||
flag: bytecode::MakeFunctionFlags::TYPE_PARAMS
|
||||
flag: bytecode::MakeFunctionFlag::TypeParams
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -4689,14 +4688,14 @@ impl Compiler {
|
||||
emit!(self, Instruction::PushNull);
|
||||
|
||||
// Set up the class function with type params
|
||||
let mut func_flags = bytecode::MakeFunctionFlags::empty();
|
||||
let mut func_flags = bytecode::MakeFunctionFlags::new();
|
||||
emit!(
|
||||
self,
|
||||
Instruction::LoadName {
|
||||
namei: dot_type_params
|
||||
}
|
||||
);
|
||||
func_flags |= bytecode::MakeFunctionFlags::TYPE_PARAMS;
|
||||
func_flags.insert(bytecode::MakeFunctionFlag::TypeParams);
|
||||
|
||||
// Create class function with closure
|
||||
self.make_closure(class_code, func_flags)?;
|
||||
@@ -4819,7 +4818,7 @@ impl Compiler {
|
||||
self.ctx = saved_ctx;
|
||||
|
||||
// Execute the type params function
|
||||
self.make_closure(type_params_code, bytecode::MakeFunctionFlags::empty())?;
|
||||
self.make_closure(type_params_code, bytecode::MakeFunctionFlags::new())?;
|
||||
emit!(self, Instruction::PushNull);
|
||||
emit!(self, Instruction::Call { argc: 0 });
|
||||
} else {
|
||||
@@ -4828,7 +4827,7 @@ impl Compiler {
|
||||
emit!(self, Instruction::PushNull);
|
||||
|
||||
// Create class function with closure
|
||||
self.make_closure(class_code, bytecode::MakeFunctionFlags::empty())?;
|
||||
self.make_closure(class_code, bytecode::MakeFunctionFlags::new())?;
|
||||
self.emit_load_const(ConstantData::Str { value: name.into() });
|
||||
|
||||
if let Some(arguments) = arguments {
|
||||
@@ -7096,12 +7095,12 @@ impl Compiler {
|
||||
}
|
||||
|
||||
self.enter_function(&name, params)?;
|
||||
let mut func_flags = bytecode::MakeFunctionFlags::empty();
|
||||
let mut func_flags = bytecode::MakeFunctionFlags::new();
|
||||
if have_defaults {
|
||||
func_flags |= bytecode::MakeFunctionFlags::DEFAULTS;
|
||||
func_flags.insert(bytecode::MakeFunctionFlag::Defaults);
|
||||
}
|
||||
if have_kwdefaults {
|
||||
func_flags |= bytecode::MakeFunctionFlags::KW_ONLY_DEFAULTS;
|
||||
func_flags.insert(bytecode::MakeFunctionFlag::KwOnlyDefaults);
|
||||
}
|
||||
|
||||
// Set qualname for lambda
|
||||
@@ -7785,7 +7784,7 @@ impl Compiler {
|
||||
self.ctx = prev_ctx;
|
||||
|
||||
// Create comprehension function with closure
|
||||
self.make_closure(code, bytecode::MakeFunctionFlags::empty())?;
|
||||
self.make_closure(code, bytecode::MakeFunctionFlags::new())?;
|
||||
emit!(self, Instruction::PushNull);
|
||||
|
||||
// Evaluate iterated item:
|
||||
|
||||
@@ -14,6 +14,7 @@ ruff_source_file = { workspace = true }
|
||||
rustpython-wtf8 = { workspace = true }
|
||||
|
||||
bitflags = { workspace = true }
|
||||
bitflagset = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
malachite-bigint = { workspace = true }
|
||||
num-complex = { workspace = true }
|
||||
|
||||
@@ -26,8 +26,8 @@ pub use crate::bytecode::{
|
||||
oparg::{
|
||||
BinaryOperator, BuildSliceArgCount, CommonConstant, ComparisonOperator, ConvertValueOparg,
|
||||
IntrinsicFunction1, IntrinsicFunction2, Invert, Label, LoadAttr, LoadSuperAttr,
|
||||
MakeFunctionFlags, NameIdx, OpArg, OpArgByte, OpArgState, OpArgType, RaiseKind, ResumeType,
|
||||
SpecialMethod, UnpackExArgs,
|
||||
MakeFunctionFlag, MakeFunctionFlags, NameIdx, OpArg, OpArgByte, OpArgState, OpArgType,
|
||||
RaiseKind, ResumeType, SpecialMethod, UnpackExArgs,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::{
|
||||
oparg::{
|
||||
self, BinaryOperator, BuildSliceArgCount, CommonConstant, ComparisonOperator,
|
||||
ConvertValueOparg, IntrinsicFunction1, IntrinsicFunction2, Invert, Label, LoadAttr,
|
||||
LoadSuperAttr, MakeFunctionFlags, NameIdx, OpArg, OpArgByte, OpArgType, RaiseKind,
|
||||
LoadSuperAttr, MakeFunctionFlag, NameIdx, OpArg, OpArgByte, OpArgType, RaiseKind,
|
||||
SpecialMethod, StoreFastLoadFast, UnpackExArgs,
|
||||
},
|
||||
},
|
||||
@@ -264,7 +264,7 @@ pub enum Instruction {
|
||||
i: Arg<u32>,
|
||||
} = 107,
|
||||
SetFunctionAttribute {
|
||||
flag: Arg<MakeFunctionFlags>,
|
||||
flag: Arg<MakeFunctionFlag>,
|
||||
} = 108,
|
||||
SetUpdate {
|
||||
i: Arg<u32>,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use bitflags::bitflags;
|
||||
|
||||
use core::fmt;
|
||||
|
||||
use crate::{
|
||||
@@ -352,34 +350,40 @@ oparg_enum!(
|
||||
}
|
||||
);
|
||||
|
||||
bitflags! {
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub struct MakeFunctionFlags: u8 {
|
||||
const CLOSURE = 0x01;
|
||||
const ANNOTATIONS = 0x02;
|
||||
const KW_ONLY_DEFAULTS = 0x04;
|
||||
const DEFAULTS = 0x08;
|
||||
const TYPE_PARAMS = 0x10;
|
||||
bitflagset::bitflag! {
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
#[repr(u8)]
|
||||
pub enum MakeFunctionFlag {
|
||||
Closure = 0,
|
||||
Annotations = 1,
|
||||
KwOnlyDefaults = 2,
|
||||
Defaults = 3,
|
||||
TypeParams = 4,
|
||||
/// PEP 649: __annotate__ function closure (instead of __annotations__ dict)
|
||||
const ANNOTATE = 0x20;
|
||||
Annotate = 5,
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u32> for MakeFunctionFlags {
|
||||
bitflagset::bitflagset! {
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub struct MakeFunctionFlags(u8): MakeFunctionFlag
|
||||
}
|
||||
|
||||
impl TryFrom<u32> for MakeFunctionFlag {
|
||||
type Error = MarshalError;
|
||||
|
||||
fn try_from(value: u32) -> Result<Self, Self::Error> {
|
||||
Self::from_bits(value as u8).ok_or(Self::Error::InvalidBytecode)
|
||||
Self::try_from(value as u8).map_err(|_| MarshalError::InvalidBytecode)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MakeFunctionFlags> for u32 {
|
||||
fn from(value: MakeFunctionFlags) -> Self {
|
||||
value.bits().into()
|
||||
impl From<MakeFunctionFlag> for u32 {
|
||||
fn from(flag: MakeFunctionFlag) -> Self {
|
||||
flag as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl OpArgType for MakeFunctionFlags {}
|
||||
impl OpArgType for MakeFunctionFlag {}
|
||||
|
||||
oparg_enum!(
|
||||
/// The possible comparison operators.
|
||||
|
||||
+30
-32
@@ -243,42 +243,40 @@ impl StackMachine {
|
||||
};
|
||||
let attr_value = self.stack.pop().expect("Expected attribute value on stack");
|
||||
|
||||
let flags = flag.get(arg);
|
||||
let flag_value = flag.get(arg);
|
||||
|
||||
// Handle ANNOTATE flag (PEP 649 style - Python 3.14+)
|
||||
// The attr_value is a function that returns annotations when called
|
||||
if flags.contains(rustpython_compiler_core::bytecode::MakeFunctionFlags::ANNOTATE) {
|
||||
if let StackValue::Function(annotate_func) = attr_value {
|
||||
// Parse the annotate function's bytecode to extract annotations
|
||||
// The pattern is: LOAD_CONST (key), LOAD_NAME (value), ... BUILD_MAP
|
||||
let annotate_code = &annotate_func.code;
|
||||
let annotations = extract_annotations_from_annotate_code(annotate_code);
|
||||
match flag_value {
|
||||
rustpython_compiler_core::bytecode::MakeFunctionFlag::Annotate => {
|
||||
// Handle ANNOTATE flag (PEP 649 style - Python 3.14+)
|
||||
if let StackValue::Function(annotate_func) = attr_value {
|
||||
let annotate_code = &annotate_func.code;
|
||||
let annotations = extract_annotations_from_annotate_code(annotate_code);
|
||||
|
||||
let updated_func = Function {
|
||||
code: func.code,
|
||||
annotations,
|
||||
};
|
||||
self.stack.push(StackValue::Function(updated_func));
|
||||
} else {
|
||||
panic!("Expected annotate function for ANNOTATE flag");
|
||||
let updated_func = Function {
|
||||
code: func.code,
|
||||
annotations,
|
||||
};
|
||||
self.stack.push(StackValue::Function(updated_func));
|
||||
} else {
|
||||
panic!("Expected annotate function for ANNOTATE flag");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Handle old ANNOTATIONS flag (Python 3.12 style)
|
||||
else if flags
|
||||
.contains(rustpython_compiler_core::bytecode::MakeFunctionFlags::ANNOTATIONS)
|
||||
{
|
||||
if let StackValue::Map(annotations) = attr_value {
|
||||
let updated_func = Function {
|
||||
code: func.code,
|
||||
annotations,
|
||||
};
|
||||
self.stack.push(StackValue::Function(updated_func));
|
||||
} else {
|
||||
panic!("Expected annotations to be a map");
|
||||
rustpython_compiler_core::bytecode::MakeFunctionFlag::Annotations => {
|
||||
// Handle old ANNOTATIONS flag (Python 3.12 style)
|
||||
if let StackValue::Map(annotations) = attr_value {
|
||||
let updated_func = Function {
|
||||
code: func.code,
|
||||
annotations,
|
||||
};
|
||||
self.stack.push(StackValue::Function(updated_func));
|
||||
} else {
|
||||
panic!("Expected annotations to be a map");
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// For other attributes, just push the function back unchanged
|
||||
self.stack.push(StackValue::Function(func));
|
||||
}
|
||||
} else {
|
||||
// For other attributes, just push the function back unchanged
|
||||
self.stack.push(StackValue::Function(func));
|
||||
}
|
||||
}
|
||||
Instruction::ReturnValue => return ControlFlow::Break(()),
|
||||
|
||||
@@ -454,75 +454,77 @@ impl PyFunction {
|
||||
/// Set function attribute based on MakeFunctionFlags
|
||||
pub(crate) fn set_function_attribute(
|
||||
&mut self,
|
||||
attr: bytecode::MakeFunctionFlags,
|
||||
attr: bytecode::MakeFunctionFlag,
|
||||
attr_value: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
use crate::builtins::PyDict;
|
||||
if attr == bytecode::MakeFunctionFlags::DEFAULTS {
|
||||
let defaults = match attr_value.downcast::<PyTuple>() {
|
||||
Ok(tuple) => tuple,
|
||||
Err(obj) => {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"__defaults__ must be a tuple, not {}",
|
||||
obj.class().name()
|
||||
)));
|
||||
}
|
||||
};
|
||||
self.defaults_and_kwdefaults.lock().0 = Some(defaults);
|
||||
} else if attr == bytecode::MakeFunctionFlags::KW_ONLY_DEFAULTS {
|
||||
let kwdefaults = match attr_value.downcast::<PyDict>() {
|
||||
Ok(dict) => dict,
|
||||
Err(obj) => {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"__kwdefaults__ must be a dict, not {}",
|
||||
obj.class().name()
|
||||
)));
|
||||
}
|
||||
};
|
||||
self.defaults_and_kwdefaults.lock().1 = Some(kwdefaults);
|
||||
} else if attr == bytecode::MakeFunctionFlags::ANNOTATIONS {
|
||||
let annotations = match attr_value.downcast::<PyDict>() {
|
||||
Ok(dict) => dict,
|
||||
Err(obj) => {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"__annotations__ must be a dict, not {}",
|
||||
obj.class().name()
|
||||
)));
|
||||
}
|
||||
};
|
||||
*self.annotations.lock() = Some(annotations);
|
||||
} else if attr == bytecode::MakeFunctionFlags::CLOSURE {
|
||||
// For closure, we need special handling
|
||||
// The closure tuple contains cell objects
|
||||
let closure_tuple = attr_value
|
||||
.clone()
|
||||
.downcast_exact::<PyTuple>(vm)
|
||||
.map_err(|obj| {
|
||||
match attr {
|
||||
bytecode::MakeFunctionFlag::Defaults => {
|
||||
let defaults = match attr_value.downcast::<PyTuple>() {
|
||||
Ok(tuple) => tuple,
|
||||
Err(obj) => {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"__defaults__ must be a tuple, not {}",
|
||||
obj.class().name()
|
||||
)));
|
||||
}
|
||||
};
|
||||
self.defaults_and_kwdefaults.lock().0 = Some(defaults);
|
||||
}
|
||||
bytecode::MakeFunctionFlag::KwOnlyDefaults => {
|
||||
let kwdefaults = match attr_value.downcast::<PyDict>() {
|
||||
Ok(dict) => dict,
|
||||
Err(obj) => {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"__kwdefaults__ must be a dict, not {}",
|
||||
obj.class().name()
|
||||
)));
|
||||
}
|
||||
};
|
||||
self.defaults_and_kwdefaults.lock().1 = Some(kwdefaults);
|
||||
}
|
||||
bytecode::MakeFunctionFlag::Annotations => {
|
||||
let annotations = match attr_value.downcast::<PyDict>() {
|
||||
Ok(dict) => dict,
|
||||
Err(obj) => {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"__annotations__ must be a dict, not {}",
|
||||
obj.class().name()
|
||||
)));
|
||||
}
|
||||
};
|
||||
*self.annotations.lock() = Some(annotations);
|
||||
}
|
||||
bytecode::MakeFunctionFlag::Closure => {
|
||||
let closure_tuple = attr_value
|
||||
.clone()
|
||||
.downcast_exact::<PyTuple>(vm)
|
||||
.map_err(|obj| {
|
||||
vm.new_type_error(format!(
|
||||
"closure must be a tuple, not {}",
|
||||
obj.class().name()
|
||||
))
|
||||
})?
|
||||
.into_pyref();
|
||||
|
||||
self.closure = Some(closure_tuple.try_into_typed::<PyCell>(vm)?);
|
||||
}
|
||||
bytecode::MakeFunctionFlag::TypeParams => {
|
||||
let type_params = attr_value.clone().downcast::<PyTuple>().map_err(|_| {
|
||||
vm.new_type_error(format!(
|
||||
"closure must be a tuple, not {}",
|
||||
obj.class().name()
|
||||
"__type_params__ must be a tuple, not {}",
|
||||
attr_value.class().name()
|
||||
))
|
||||
})?
|
||||
.into_pyref();
|
||||
|
||||
self.closure = Some(closure_tuple.try_into_typed::<PyCell>(vm)?);
|
||||
} else if attr == bytecode::MakeFunctionFlags::TYPE_PARAMS {
|
||||
let type_params = attr_value.clone().downcast::<PyTuple>().map_err(|_| {
|
||||
vm.new_type_error(format!(
|
||||
"__type_params__ must be a tuple, not {}",
|
||||
attr_value.class().name()
|
||||
))
|
||||
})?;
|
||||
*self.type_params.lock() = type_params;
|
||||
} else if attr == bytecode::MakeFunctionFlags::ANNOTATE {
|
||||
// PEP 649: Store the __annotate__ function closure
|
||||
if !attr_value.is_callable() {
|
||||
return Err(vm.new_type_error("__annotate__ must be callable"));
|
||||
})?;
|
||||
*self.type_params.lock() = type_params;
|
||||
}
|
||||
bytecode::MakeFunctionFlag::Annotate => {
|
||||
if !attr_value.is_callable() {
|
||||
return Err(vm.new_type_error("__annotate__ must be callable"));
|
||||
}
|
||||
*self.annotate.lock() = Some(attr_value);
|
||||
}
|
||||
*self.annotate.lock() = Some(attr_value);
|
||||
} else {
|
||||
unreachable!("This is a compiler bug");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -6861,7 +6861,7 @@ impl ExecutingFrame<'_> {
|
||||
fn execute_set_function_attribute(
|
||||
&mut self,
|
||||
vm: &VirtualMachine,
|
||||
attr: bytecode::MakeFunctionFlags,
|
||||
attr: bytecode::MakeFunctionFlag,
|
||||
) -> FrameResult {
|
||||
// SET_FUNCTION_ATTRIBUTE sets attributes on a function
|
||||
// Stack: [..., attr_value, func] -> [..., func]
|
||||
|
||||
Reference in new issue
Block a user