Skip to content

Commit 55fbd0e

Browse files
committed
stack is [Option<PyObjectRef>]
1 parent b9d8da0 commit 55fbd0e

File tree

8 files changed

+370
-357
lines changed

8 files changed

+370
-357
lines changed

Lib/test/test_xml_etree.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2301,7 +2301,6 @@ def test_bug_xmltoolkit62(self):
23012301
self.assertEqual(t.find('.//paragraph').text,
23022302
'A new cultivar of Begonia plant named \u2018BCT9801BEG\u2019.')
23032303

2304-
@unittest.expectedFailure # TODO: RUSTPYTHON
23052304
@unittest.skipIf(sys.gettrace(), "Skips under coverage.")
23062305
def test_bug_xmltoolkit63(self):
23072306
# Check reference leak.

crates/codegen/src/compile.rs

Lines changed: 76 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,6 @@ enum NameUsage {
9898
Delete,
9999
}
100100

101-
enum CallType {
102-
Positional { nargs: u32 },
103-
Keyword { nargs: u32 },
104-
Ex { has_kwargs: bool },
105-
}
106-
107101
fn is_forbidden_name(name: &str) -> bool {
108102
// See https://docs.python.org/3/library/constants.html#built-in-constants
109103
const BUILTIN_CONSTANTS: &[&str] = &["__debug__"];
@@ -1037,10 +1031,11 @@ impl Compiler {
10371031

10381032
// Call __exit__(None, None, None) - compiler_call_exit_with_nones
10391033
// Stack: [..., __exit__] or [..., return_value, __exit__]
1034+
emit!(self, Instruction::PushNull);
10401035
self.emit_load_const(ConstantData::None);
10411036
self.emit_load_const(ConstantData::None);
10421037
self.emit_load_const(ConstantData::None);
1043-
emit!(self, Instruction::CallFunctionPositional { nargs: 3 });
1038+
emit!(self, Instruction::Call { nargs: 3 });
10441039

10451040
// For async with, await the result
10461041
if matches!(info.fb_type, FBlockType::AsyncWith) {
@@ -1875,13 +1870,14 @@ impl Compiler {
18751870

18761871
let assertion_error = self.name("AssertionError");
18771872
emit!(self, Instruction::LoadGlobal(assertion_error));
1873+
emit!(self, Instruction::PushNull);
18781874
match msg {
18791875
Some(e) => {
18801876
self.compile_expression(e)?;
1881-
emit!(self, Instruction::CallFunctionPositional { nargs: 1 });
1877+
emit!(self, Instruction::Call { nargs: 1 });
18821878
}
18831879
None => {
1884-
emit!(self, Instruction::CallFunctionPositional { nargs: 0 });
1880+
emit!(self, Instruction::Call { nargs: 0 });
18851881
}
18861882
}
18871883
emit!(
@@ -2095,14 +2091,15 @@ impl Compiler {
20952091
fn prepare_decorators(&mut self, decorator_list: &[Decorator]) -> CompileResult<()> {
20962092
for decorator in decorator_list {
20972093
self.compile_expression(&decorator.expression)?;
2094+
emit!(self, Instruction::PushNull);
20982095
}
20992096
Ok(())
21002097
}
21012098

21022099
fn apply_decorators(&mut self, decorator_list: &[Decorator]) {
2103-
// Apply decorators:
2100+
// Apply decorators - each pops [decorator, NULL, arg] and pushes result
21042101
for _ in decorator_list {
2105-
emit!(self, Instruction::CallFunctionPositional { nargs: 1 });
2102+
emit!(self, Instruction::Call { nargs: 1 });
21062103
}
21072104
}
21082105

@@ -2142,9 +2139,10 @@ impl Compiler {
21422139

21432140
// Create type params function with closure
21442141
self.make_closure(code, bytecode::MakeFunctionFlags::empty())?;
2142+
emit!(self, Instruction::PushNull);
21452143

21462144
// Call the function immediately
2147-
emit!(self, Instruction::CallFunctionPositional { nargs: 0 });
2145+
emit!(self, Instruction::Call { nargs: 0 });
21482146

21492147
Ok(())
21502148
}
@@ -3224,11 +3222,6 @@ impl Compiler {
32243222
num_typeparam_args += 1;
32253223
}
32263224

3227-
// SWAP if we have both
3228-
if num_typeparam_args == 2 {
3229-
emit!(self, Instruction::Swap { index: 2 });
3230-
}
3231-
32323225
// Enter type params scope
32333226
let type_params_name = format!("<generic parameters of {name}>");
32343227
self.push_output(
@@ -3308,22 +3301,39 @@ impl Compiler {
33083301
self.make_closure(type_params_code, bytecode::MakeFunctionFlags::empty())?;
33093302

33103303
// Call the closure
3304+
// Call expects stack: [callable, self_or_null, arg1, ..., argN]
33113305
if num_typeparam_args > 0 {
3306+
// Stack: [arg1, ..., argN, closure]
3307+
// Need: [closure, NULL, arg1, ..., argN]
3308+
let swap_depth = (num_typeparam_args + 1) as u32;
3309+
emit!(self, Instruction::Swap { index: swap_depth });
3310+
// Stack: [closure, ..., argN, arg1]
3311+
emit!(self, Instruction::PushNull);
3312+
// Stack: [closure, ..., argN, arg1, NULL]
3313+
emit!(self, Instruction::Swap { index: swap_depth });
3314+
// Stack: [closure, NULL, ..., argN, arg1]
3315+
// For N>1, need to reverse args back to original order
3316+
if num_typeparam_args > 1 {
3317+
emit!(
3318+
self,
3319+
Instruction::Reverse {
3320+
amount: num_typeparam_args as u32
3321+
}
3322+
);
3323+
}
3324+
// Stack: [closure, NULL, arg1, ..., argN]
33123325
emit!(
33133326
self,
3314-
Instruction::Swap {
3315-
index: (num_typeparam_args + 1) as u32
3316-
}
3317-
);
3318-
emit!(
3319-
self,
3320-
Instruction::CallFunctionPositional {
3327+
Instruction::Call {
33213328
nargs: num_typeparam_args as u32
33223329
}
33233330
);
33243331
} else {
3325-
// No arguments, just call the closure
3326-
emit!(self, Instruction::CallFunctionPositional { nargs: 0 });
3332+
// Stack: [closure]
3333+
emit!(self, Instruction::PushNull);
3334+
// Stack: [closure, NULL]
3335+
// Call pops: args (0), then self_or_null (NULL), then callable (closure)
3336+
emit!(self, Instruction::Call { nargs: 0 });
33273337
}
33283338
}
33293339

@@ -3691,6 +3701,7 @@ impl Compiler {
36913701

36923702
// Generate class creation code
36933703
emit!(self, Instruction::LoadBuildClass);
3704+
emit!(self, Instruction::PushNull);
36943705

36953706
// Set up the class function with type params
36963707
let mut func_flags = bytecode::MakeFunctionFlags::empty();
@@ -3720,24 +3731,30 @@ impl Compiler {
37203731
if let Some(arguments) = arguments
37213732
&& !arguments.keywords.is_empty()
37223733
{
3734+
let mut kwarg_names = vec![];
37233735
for keyword in &arguments.keywords {
37243736
if let Some(name) = &keyword.arg {
3725-
self.emit_load_const(ConstantData::Str {
3737+
kwarg_names.push(ConstantData::Str {
37263738
value: name.as_str().into(),
37273739
});
3740+
} else {
3741+
panic!("keyword argument name must be set");
37283742
}
37293743
self.compile_expression(&keyword.value)?;
37303744
}
3745+
self.emit_load_const(ConstantData::Tuple {
3746+
elements: kwarg_names,
3747+
});
37313748
emit!(
37323749
self,
3733-
Instruction::CallFunctionKeyword {
3750+
Instruction::CallKw {
37343751
nargs: nargs
37353752
+ u32::try_from(arguments.keywords.len())
37363753
.expect("too many keyword arguments")
37373754
}
37383755
);
37393756
} else {
3740-
emit!(self, Instruction::CallFunctionPositional { nargs });
3757+
emit!(self, Instruction::Call { nargs });
37413758
}
37423759

37433760
// Return the created class
@@ -3748,21 +3765,22 @@ impl Compiler {
37483765

37493766
// Execute the type params function
37503767
self.make_closure(type_params_code, bytecode::MakeFunctionFlags::empty())?;
3751-
emit!(self, Instruction::CallFunctionPositional { nargs: 0 });
3768+
emit!(self, Instruction::PushNull);
3769+
emit!(self, Instruction::Call { nargs: 0 });
37523770
} else {
37533771
// Non-generic class: standard path
37543772
emit!(self, Instruction::LoadBuildClass);
3773+
emit!(self, Instruction::PushNull);
37553774

37563775
// Create class function with closure
37573776
self.make_closure(class_code, bytecode::MakeFunctionFlags::empty())?;
37583777
self.emit_load_const(ConstantData::Str { value: name.into() });
37593778

3760-
let call = if let Some(arguments) = arguments {
3761-
self.compile_call_inner(2, arguments)?
3779+
if let Some(arguments) = arguments {
3780+
self.compile_call_helper(2, arguments)?;
37623781
} else {
3763-
CallType::Positional { nargs: 2 }
3764-
};
3765-
self.compile_normal_call(call);
3782+
emit!(self, Instruction::Call { nargs: 2 });
3783+
}
37663784
}
37673785

37683786
// Step 4: Apply decorators and store (common to both paths)
@@ -3912,10 +3930,11 @@ impl Compiler {
39123930
// Stack: [..., __exit__]
39133931
// Call __exit__(None, None, None)
39143932
self.set_source_range(with_range);
3933+
emit!(self, Instruction::PushNull);
39153934
self.emit_load_const(ConstantData::None);
39163935
self.emit_load_const(ConstantData::None);
39173936
self.emit_load_const(ConstantData::None);
3918-
emit!(self, Instruction::CallFunctionPositional { nargs: 3 });
3937+
emit!(self, Instruction::Call { nargs: 3 });
39193938
if is_async {
39203939
emit!(self, Instruction::GetAwaitable);
39213940
self.emit_load_const(ConstantData::None);
@@ -6087,51 +6106,32 @@ impl Compiler {
60876106
}
60886107

60896108
fn compile_call(&mut self, func: &Expr, args: &Arguments) -> CompileResult<()> {
6090-
// Method call: obj → LOAD_ATTR_METHOD → [method, self_or_null] → args → CALL_WITH_SELF
6091-
// Regular call: func → args → CALL
6109+
// Method call: obj → LOAD_ATTR_METHOD → [method, self_or_null] → args → CALL
6110+
// Regular call: func → PUSH_NULL → args → CALL
60926111
if let Expr::Attribute(ExprAttribute { value, attr, .. }) = &func {
60936112
// Method call: compile object, then LOAD_ATTR_METHOD
60946113
// LOAD_ATTR_METHOD pushes [method, self_or_null] on stack
60956114
self.compile_expression(value)?;
60966115
let idx = self.name(attr.as_str());
60976116
emit!(self, Instruction::LoadAttrMethod { idx });
6098-
// Compile args, then use CallWithSelf which handles self_or_null
6099-
let call = self.compile_call_inner(0, args)?;
6100-
self.compile_call_with_self(call);
6117+
self.compile_call_helper(0, args)?;
61016118
} else {
6102-
// Regular call: just compile function and args
6119+
// Regular call: push func, then NULL for self_or_null slot
6120+
// Stack layout: [func, NULL, args...] - same as method call [func, self, args...]
61036121
self.compile_expression(func)?;
6104-
let call = self.compile_call_inner(0, args)?;
6105-
self.compile_normal_call(call);
6122+
emit!(self, Instruction::PushNull);
6123+
self.compile_call_helper(0, args)?;
61066124
}
61076125
Ok(())
61086126
}
61096127

6110-
fn compile_call_with_self(&mut self, ty: CallType) {
6111-
match ty {
6112-
CallType::Positional { nargs } => {
6113-
emit!(self, Instruction::CallWithSelf { nargs })
6114-
}
6115-
CallType::Keyword { nargs } => emit!(self, Instruction::CallWithSelfKw { nargs }),
6116-
CallType::Ex { has_kwargs } => emit!(self, Instruction::CallWithSelfEx { has_kwargs }),
6117-
}
6118-
}
6119-
6120-
fn compile_normal_call(&mut self, ty: CallType) {
6121-
match ty {
6122-
CallType::Positional { nargs } => {
6123-
emit!(self, Instruction::CallFunctionPositional { nargs })
6124-
}
6125-
CallType::Keyword { nargs } => emit!(self, Instruction::CallFunctionKeyword { nargs }),
6126-
CallType::Ex { has_kwargs } => emit!(self, Instruction::CallFunctionEx { has_kwargs }),
6127-
}
6128-
}
6129-
6130-
fn compile_call_inner(
6128+
/// Compile call arguments and emit the appropriate CALL instruction.
6129+
/// This is shared between compiler_call and compiler_class.
6130+
fn compile_call_helper(
61316131
&mut self,
61326132
additional_positional: u32,
61336133
arguments: &Arguments,
6134-
) -> CompileResult<CallType> {
6134+
) -> CompileResult<()> {
61356135
let count = u32::try_from(arguments.len()).unwrap() + additional_positional;
61366136

61376137
// Normal arguments:
@@ -6144,7 +6144,7 @@ impl Compiler {
61446144
}
61456145
}
61466146

6147-
let call = if unpack || has_double_star {
6147+
if unpack || has_double_star {
61486148
// Create a tuple with positional args:
61496149
if unpack {
61506150
emit!(self, Instruction::BuildTupleFromTuples { size });
@@ -6157,7 +6157,7 @@ impl Compiler {
61576157
if has_kwargs {
61586158
self.compile_keywords(&arguments.keywords)?;
61596159
}
6160-
CallType::Ex { has_kwargs }
6160+
emit!(self, Instruction::CallFunctionEx { has_kwargs });
61616161
} else if !arguments.keywords.is_empty() {
61626162
let mut kwarg_names = vec![];
61636163
for keyword in &arguments.keywords {
@@ -6175,12 +6175,12 @@ impl Compiler {
61756175
self.emit_load_const(ConstantData::Tuple {
61766176
elements: kwarg_names,
61776177
});
6178-
CallType::Keyword { nargs: count }
6178+
emit!(self, Instruction::CallKw { nargs: count });
61796179
} else {
6180-
CallType::Positional { nargs: count }
6181-
};
6180+
emit!(self, Instruction::Call { nargs: count });
6181+
}
61826182

6183-
Ok(call)
6183+
Ok(())
61846184
}
61856185

61866186
// Given a vector of expr / star expr generate code which gives either
@@ -6412,6 +6412,7 @@ impl Compiler {
64126412

64136413
// Create comprehension function with closure
64146414
self.make_closure(code, bytecode::MakeFunctionFlags::empty())?;
6415+
emit!(self, Instruction::PushNull);
64156416

64166417
// Evaluate iterated item:
64176418
self.compile_expression(&generators[0].iter)?;
@@ -6425,7 +6426,7 @@ impl Compiler {
64256426
};
64266427

64276428
// Call just created <listcomp> function:
6428-
emit!(self, Instruction::CallFunctionPositional { nargs: 1 });
6429+
emit!(self, Instruction::Call { nargs: 1 });
64296430
if is_async_list_set_dict_comprehension {
64306431
emit!(self, Instruction::GetAwaitable);
64316432
self.emit_load_const(ConstantData::None);
@@ -6841,10 +6842,11 @@ impl Compiler {
68416842
match action {
68426843
UnwindAction::With { is_async } => {
68436844
// compiler_call_exit_with_nones
6845+
emit!(self, Instruction::PushNull);
68446846
self.emit_load_const(ConstantData::None);
68456847
self.emit_load_const(ConstantData::None);
68466848
self.emit_load_const(ConstantData::None);
6847-
emit!(self, Instruction::CallFunctionPositional { nargs: 3 });
6849+
emit!(self, Instruction::Call { nargs: 3 });
68486850

68496851
if is_async {
68506852
emit!(self, Instruction::GetAwaitable);

0 commit comments

Comments
 (0)