Skip to content

Commit 5a37003

Browse files
committed
stack is [Option<PyObjectRef>]
1 parent e191864 commit 5a37003

File tree

8 files changed

+359
-327
lines changed

8 files changed

+359
-327
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: 65 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,10 +1037,11 @@ impl Compiler {
10371037

10381038
// Call __exit__(None, None, None) - compiler_call_exit_with_nones
10391039
// Stack: [..., __exit__] or [..., return_value, __exit__]
1040+
emit!(self, Instruction::PushNull);
10401041
self.emit_load_const(ConstantData::None);
10411042
self.emit_load_const(ConstantData::None);
10421043
self.emit_load_const(ConstantData::None);
1043-
emit!(self, Instruction::CallFunctionPositional { nargs: 3 });
1044+
emit!(self, Instruction::Call { nargs: 3 });
10441045

10451046
// For async with, await the result
10461047
if matches!(info.fb_type, FBlockType::AsyncWith) {
@@ -1875,13 +1876,14 @@ impl Compiler {
18751876

18761877
let assertion_error = self.name("AssertionError");
18771878
emit!(self, Instruction::LoadGlobal(assertion_error));
1879+
emit!(self, Instruction::PushNull);
18781880
match msg {
18791881
Some(e) => {
18801882
self.compile_expression(e)?;
1881-
emit!(self, Instruction::CallFunctionPositional { nargs: 1 });
1883+
emit!(self, Instruction::Call { nargs: 1 });
18821884
}
18831885
None => {
1884-
emit!(self, Instruction::CallFunctionPositional { nargs: 0 });
1886+
emit!(self, Instruction::Call { nargs: 0 });
18851887
}
18861888
}
18871889
emit!(
@@ -2095,14 +2097,16 @@ impl Compiler {
20952097
fn prepare_decorators(&mut self, decorator_list: &[Decorator]) -> CompileResult<()> {
20962098
for decorator in decorator_list {
20972099
self.compile_expression(&decorator.expression)?;
2100+
// PUSH_NULL for self_or_null slot (decorator is not a method call)
2101+
emit!(self, Instruction::PushNull);
20982102
}
20992103
Ok(())
21002104
}
21012105

21022106
fn apply_decorators(&mut self, decorator_list: &[Decorator]) {
2103-
// Apply decorators:
2107+
// Apply decorators - each pops [decorator, NULL, arg] and pushes result
21042108
for _ in decorator_list {
2105-
emit!(self, Instruction::CallFunctionPositional { nargs: 1 });
2109+
emit!(self, Instruction::Call { nargs: 1 });
21062110
}
21072111
}
21082112

@@ -2142,9 +2146,10 @@ impl Compiler {
21422146

21432147
// Create type params function with closure
21442148
self.make_closure(code, bytecode::MakeFunctionFlags::empty())?;
2149+
emit!(self, Instruction::PushNull);
21452150

21462151
// Call the function immediately
2147-
emit!(self, Instruction::CallFunctionPositional { nargs: 0 });
2152+
emit!(self, Instruction::Call { nargs: 0 });
21482153

21492154
Ok(())
21502155
}
@@ -3224,11 +3229,6 @@ impl Compiler {
32243229
num_typeparam_args += 1;
32253230
}
32263231

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

33103310
// Call the closure
3311+
// Call expects stack: [callable, self_or_null, arg1, ..., argN]
33113312
if num_typeparam_args > 0 {
3313+
// Stack: [arg1, ..., argN, closure]
3314+
// Need: [closure, NULL, arg1, ..., argN]
3315+
let swap_depth = (num_typeparam_args + 1) as u32;
3316+
emit!(self, Instruction::Swap { index: swap_depth });
3317+
// Stack: [closure, ..., argN, arg1]
3318+
emit!(self, Instruction::PushNull);
3319+
// Stack: [closure, ..., argN, arg1, NULL]
3320+
emit!(self, Instruction::Swap { index: swap_depth });
3321+
// Stack: [closure, NULL, ..., argN, arg1]
3322+
// For N>1, need to reverse args back to original order
3323+
if num_typeparam_args > 1 {
3324+
emit!(
3325+
self,
3326+
Instruction::Reverse {
3327+
amount: num_typeparam_args as u32
3328+
}
3329+
);
3330+
}
3331+
// Stack: [closure, NULL, arg1, ..., argN]
33123332
emit!(
33133333
self,
3314-
Instruction::Swap {
3315-
index: (num_typeparam_args + 1) as u32
3316-
}
3317-
);
3318-
emit!(
3319-
self,
3320-
Instruction::CallFunctionPositional {
3334+
Instruction::Call {
33213335
nargs: num_typeparam_args as u32
33223336
}
33233337
);
33243338
} else {
3325-
// No arguments, just call the closure
3326-
emit!(self, Instruction::CallFunctionPositional { nargs: 0 });
3339+
// Stack: [closure]
3340+
emit!(self, Instruction::PushNull);
3341+
// Stack: [closure, NULL] - already correct layout
3342+
// Call pops: args (0), then self_or_null (NULL), then callable (closure)
3343+
emit!(self, Instruction::Call { nargs: 0 });
33273344
}
33283345
}
33293346

@@ -3691,6 +3708,7 @@ impl Compiler {
36913708

36923709
// Generate class creation code
36933710
emit!(self, Instruction::LoadBuildClass);
3711+
emit!(self, Instruction::PushNull);
36943712

36953713
// Set up the class function with type params
36963714
let mut func_flags = bytecode::MakeFunctionFlags::empty();
@@ -3720,24 +3738,30 @@ impl Compiler {
37203738
if let Some(arguments) = arguments
37213739
&& !arguments.keywords.is_empty()
37223740
{
3741+
let mut kwarg_names = vec![];
37233742
for keyword in &arguments.keywords {
37243743
if let Some(name) = &keyword.arg {
3725-
self.emit_load_const(ConstantData::Str {
3744+
kwarg_names.push(ConstantData::Str {
37263745
value: name.as_str().into(),
37273746
});
3747+
} else {
3748+
panic!("keyword argument name must be set");
37283749
}
37293750
self.compile_expression(&keyword.value)?;
37303751
}
3752+
self.emit_load_const(ConstantData::Tuple {
3753+
elements: kwarg_names,
3754+
});
37313755
emit!(
37323756
self,
3733-
Instruction::CallFunctionKeyword {
3757+
Instruction::CallKw {
37343758
nargs: nargs
37353759
+ u32::try_from(arguments.keywords.len())
37363760
.expect("too many keyword arguments")
37373761
}
37383762
);
37393763
} else {
3740-
emit!(self, Instruction::CallFunctionPositional { nargs });
3764+
emit!(self, Instruction::Call { nargs });
37413765
}
37423766

37433767
// Return the created class
@@ -3748,10 +3772,12 @@ impl Compiler {
37483772

37493773
// Execute the type params function
37503774
self.make_closure(type_params_code, bytecode::MakeFunctionFlags::empty())?;
3751-
emit!(self, Instruction::CallFunctionPositional { nargs: 0 });
3775+
emit!(self, Instruction::PushNull);
3776+
emit!(self, Instruction::Call { nargs: 0 });
37523777
} else {
37533778
// Non-generic class: standard path
37543779
emit!(self, Instruction::LoadBuildClass);
3780+
emit!(self, Instruction::PushNull);
37553781

37563782
// Create class function with closure
37573783
self.make_closure(class_code, bytecode::MakeFunctionFlags::empty())?;
@@ -3762,7 +3788,7 @@ impl Compiler {
37623788
} else {
37633789
CallType::Positional { nargs: 2 }
37643790
};
3765-
self.compile_normal_call(call);
3791+
self.compile_call_with_self(call);
37663792
}
37673793

37683794
// Step 4: Apply decorators and store (common to both paths)
@@ -3912,10 +3938,11 @@ impl Compiler {
39123938
// Stack: [..., __exit__]
39133939
// Call __exit__(None, None, None)
39143940
self.set_source_range(with_range);
3941+
emit!(self, Instruction::PushNull);
39153942
self.emit_load_const(ConstantData::None);
39163943
self.emit_load_const(ConstantData::None);
39173944
self.emit_load_const(ConstantData::None);
3918-
emit!(self, Instruction::CallFunctionPositional { nargs: 3 });
3945+
emit!(self, Instruction::Call { nargs: 3 });
39193946
if is_async {
39203947
emit!(self, Instruction::GetAwaitable);
39213948
self.emit_load_const(ConstantData::None);
@@ -6088,41 +6115,33 @@ impl Compiler {
60886115

60896116
fn compile_call(&mut self, func: &Expr, args: &Arguments) -> CompileResult<()> {
60906117
// Method call: obj → LOAD_ATTR_METHOD → [method, self_or_null] → args → CALL_WITH_SELF
6091-
// Regular call: func → args → CALL
6118+
// Regular call: func → PUSH_NULL → args → CALL_WITH_SELF
60926119
if let Expr::Attribute(ExprAttribute { value, attr, .. }) = &func {
60936120
// Method call: compile object, then LOAD_ATTR_METHOD
60946121
// LOAD_ATTR_METHOD pushes [method, self_or_null] on stack
60956122
self.compile_expression(value)?;
60966123
let idx = self.name(attr.as_str());
60976124
emit!(self, Instruction::LoadAttrMethod { idx });
6098-
// Compile args, then use CallWithSelf which handles self_or_null
6125+
// Compile args, then use Call which handles self_or_null
60996126
let call = self.compile_call_inner(0, args)?;
61006127
self.compile_call_with_self(call);
61016128
} else {
6102-
// Regular call: just compile function and args
6129+
// Regular call: push func, then NULL for self_or_null slot
6130+
// Stack layout: [func, NULL, args...] - same as method call [func, self, args...]
61036131
self.compile_expression(func)?;
6132+
emit!(self, Instruction::PushNull);
61046133
let call = self.compile_call_inner(0, args)?;
6105-
self.compile_normal_call(call);
6134+
self.compile_call_with_self(call);
61066135
}
61076136
Ok(())
61086137
}
61096138

61106139
fn compile_call_with_self(&mut self, ty: CallType) {
61116140
match ty {
61126141
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 })
6142+
emit!(self, Instruction::Call { nargs })
61246143
}
6125-
CallType::Keyword { nargs } => emit!(self, Instruction::CallFunctionKeyword { nargs }),
6144+
CallType::Keyword { nargs } => emit!(self, Instruction::CallKw { nargs }),
61266145
CallType::Ex { has_kwargs } => emit!(self, Instruction::CallFunctionEx { has_kwargs }),
61276146
}
61286147
}
@@ -6412,6 +6431,7 @@ impl Compiler {
64126431

64136432
// Create comprehension function with closure
64146433
self.make_closure(code, bytecode::MakeFunctionFlags::empty())?;
6434+
emit!(self, Instruction::PushNull);
64156435

64166436
// Evaluate iterated item:
64176437
self.compile_expression(&generators[0].iter)?;
@@ -6425,7 +6445,7 @@ impl Compiler {
64256445
};
64266446

64276447
// Call just created <listcomp> function:
6428-
emit!(self, Instruction::CallFunctionPositional { nargs: 1 });
6448+
emit!(self, Instruction::Call { nargs: 1 });
64296449
if is_async_list_set_dict_comprehension {
64306450
emit!(self, Instruction::GetAwaitable);
64316451
self.emit_load_const(ConstantData::None);
@@ -6841,10 +6861,11 @@ impl Compiler {
68416861
match action {
68426862
UnwindAction::With { is_async } => {
68436863
// compiler_call_exit_with_nones
6864+
emit!(self, Instruction::PushNull);
68446865
self.emit_load_const(ConstantData::None);
68456866
self.emit_load_const(ConstantData::None);
68466867
self.emit_load_const(ConstantData::None);
6847-
emit!(self, Instruction::CallFunctionPositional { nargs: 3 });
6868+
emit!(self, Instruction::Call { nargs: 3 });
68486869

68496870
if is_async {
68506871
emit!(self, Instruction::GetAwaitable);

0 commit comments

Comments
 (0)