Skip to content

Commit 012a6fa

Browse files
committed
fix again
1 parent 29d2d88 commit 012a6fa

File tree

2 files changed

+95
-46
lines changed

2 files changed

+95
-46
lines changed

crates/codegen/src/compile.rs

Lines changed: 94 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3305,16 +3305,23 @@ impl Compiler {
33053305
if num_typeparam_args > 0 {
33063306
// Stack: [arg1, ..., argN, closure]
33073307
// Need: [closure, NULL, arg1, ..., argN]
3308-
let reverse_amount = (num_typeparam_args + 1) as u32;
3309-
emit!(
3310-
self,
3311-
Instruction::Reverse {
3312-
amount: reverse_amount
3308+
match num_typeparam_args {
3309+
1 => {
3310+
// Stack: [arg1, closure]
3311+
emit!(self, Instruction::Swap { index: 2 }); // [closure, arg1]
3312+
emit!(self, Instruction::PushNull); // [closure, arg1, NULL]
3313+
emit!(self, Instruction::Swap { index: 2 }); // [closure, NULL, arg1]
33133314
}
3314-
);
3315-
// Stack: [closure, argN, ..., arg1]
3316-
emit!(self, Instruction::PushNull);
3317-
// Stack: [closure, argN, ..., arg1, NULL]
3315+
2 => {
3316+
// Stack: [arg1, arg2, closure]
3317+
emit!(self, Instruction::Swap { index: 3 }); // [closure, arg2, arg1]
3318+
emit!(self, Instruction::Swap { index: 2 }); // [closure, arg1, arg2]
3319+
emit!(self, Instruction::PushNull); // [closure, arg1, arg2, NULL]
3320+
emit!(self, Instruction::Swap { index: 3 }); // [closure, NULL, arg2, arg1]
3321+
emit!(self, Instruction::Swap { index: 2 }); // [closure, NULL, arg1, arg2]
3322+
}
3323+
_ => unreachable!("only defaults and kwdefaults are supported"),
3324+
}
33183325
emit!(
33193326
self,
33203327
Instruction::Call {
@@ -3325,7 +3332,6 @@ impl Compiler {
33253332
// Stack: [closure]
33263333
emit!(self, Instruction::PushNull);
33273334
// Stack: [closure, NULL]
3328-
// Call pops: args (0), then self_or_null (NULL), then callable (closure)
33293335
emit!(self, Instruction::Call { nargs: 0 });
33303336
}
33313337
}
@@ -3705,49 +3711,91 @@ impl Compiler {
37053711
self.make_closure(class_code, func_flags)?;
37063712
self.emit_load_const(ConstantData::Str { value: name.into() });
37073713

3708-
// Compile original bases
3709-
let base_count = if let Some(arguments) = arguments {
3710-
for arg in &arguments.args {
3711-
self.compile_expression(arg)?;
3714+
// Compile bases and call __build_class__
3715+
// Check for starred bases or **kwargs
3716+
let has_starred = arguments
3717+
.is_some_and(|args| args.args.iter().any(|arg| matches!(arg, Expr::Starred(_))));
3718+
let has_double_star =
3719+
arguments.is_some_and(|args| args.keywords.iter().any(|kw| kw.arg.is_none()));
3720+
3721+
if has_starred || has_double_star {
3722+
// Use CallFunctionEx for *bases or **kwargs
3723+
// Stack has: [__build_class__, NULL, class_func, name]
3724+
// Need to build: args tuple = (class_func, name, *bases, .generic_base)
3725+
3726+
// Compile bases with gather_elements (handles starred)
3727+
let (size, unpack) = if let Some(arguments) = arguments {
3728+
self.gather_elements(2, &arguments.args)? // 2 = class_func + name already on stack
3729+
} else {
3730+
// Just class_func and name (no bases)
3731+
(2, false)
3732+
};
3733+
3734+
// Add .generic_base as final base
3735+
emit!(self, Instruction::LoadName(dot_generic_base));
3736+
3737+
// Build args tuple
3738+
if unpack {
3739+
// Starred: gather_elements produced tuples on stack
3740+
emit!(self, Instruction::BuildTuple { size: 1 }); // (.generic_base,)
3741+
emit!(self, Instruction::BuildTupleFromTuples { size: size + 1 });
3742+
} else {
3743+
// No starred: individual elements on stack
3744+
// size includes class_func + name + bases count, +1 for .generic_base
3745+
emit!(self, Instruction::BuildTuple { size: size + 1 });
3746+
}
3747+
3748+
// Build kwargs if needed
3749+
let has_kwargs = arguments.is_some_and(|args| !args.keywords.is_empty());
3750+
if has_kwargs {
3751+
self.compile_keywords(&arguments.unwrap().keywords)?;
37123752
}
3713-
arguments.args.len()
3753+
emit!(self, Instruction::CallFunctionEx { has_kwargs });
37143754
} else {
3715-
0
3716-
};
3755+
// Simple case: no starred bases, no **kwargs
3756+
// Compile bases normally
3757+
let base_count = if let Some(arguments) = arguments {
3758+
for arg in &arguments.args {
3759+
self.compile_expression(arg)?;
3760+
}
3761+
arguments.args.len()
3762+
} else {
3763+
0
3764+
};
37173765

3718-
// Load .generic_base as the last base
3719-
emit!(self, Instruction::LoadName(dot_generic_base));
3766+
// Load .generic_base as the last base
3767+
emit!(self, Instruction::LoadName(dot_generic_base));
37203768

3721-
let nargs = 2 + u32::try_from(base_count).expect("too many base classes") + 1; // function, name, bases..., generic_base
3769+
let nargs = 2 + u32::try_from(base_count).expect("too many base classes") + 1;
37223770

3723-
// Handle keyword arguments
3724-
if let Some(arguments) = arguments
3725-
&& !arguments.keywords.is_empty()
3726-
{
3727-
let mut kwarg_names = vec![];
3728-
for keyword in &arguments.keywords {
3729-
let name = keyword
3730-
.arg
3731-
.as_ref()
3732-
.expect("keyword argument name must be set");
3733-
kwarg_names.push(ConstantData::Str {
3734-
value: name.as_str().into(),
3771+
// Handle keyword arguments (no **kwargs here)
3772+
if let Some(arguments) = arguments
3773+
&& !arguments.keywords.is_empty()
3774+
{
3775+
let mut kwarg_names = vec![];
3776+
for keyword in &arguments.keywords {
3777+
let name = keyword.arg.as_ref().expect(
3778+
"keyword argument name must be set (no **kwargs in this branch)",
3779+
);
3780+
kwarg_names.push(ConstantData::Str {
3781+
value: name.as_str().into(),
3782+
});
3783+
self.compile_expression(&keyword.value)?;
3784+
}
3785+
self.emit_load_const(ConstantData::Tuple {
3786+
elements: kwarg_names,
37353787
});
3736-
self.compile_expression(&keyword.value)?;
3788+
emit!(
3789+
self,
3790+
Instruction::CallKw {
3791+
nargs: nargs
3792+
+ u32::try_from(arguments.keywords.len())
3793+
.expect("too many keyword arguments")
3794+
}
3795+
);
3796+
} else {
3797+
emit!(self, Instruction::Call { nargs });
37373798
}
3738-
self.emit_load_const(ConstantData::Tuple {
3739-
elements: kwarg_names,
3740-
});
3741-
emit!(
3742-
self,
3743-
Instruction::CallKw {
3744-
nargs: nargs
3745-
+ u32::try_from(arguments.keywords.len())
3746-
.expect("too many keyword arguments")
3747-
}
3748-
);
3749-
} else {
3750-
emit!(self, Instruction::Call { nargs });
37513799
}
37523800

37533801
// Return the created class

crates/compiler-core/src/bytecode.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,6 +2062,7 @@ impl Instruction {
20622062
PopJumpIfTrue { target } => w!(POP_JUMP_IF_TRUE, target),
20632063
PopTop => w!(POP_TOP),
20642064
PushExcInfo => w!(PUSH_EXC_INFO),
2065+
PushNull => w!(PUSH_NULL),
20652066
RaiseVarargs { kind } => w!(RAISE_VARARGS, ?kind),
20662067
Reraise { depth } => w!(RERAISE, depth),
20672068
Resume { arg } => w!(RESUME, arg),

0 commit comments

Comments
 (0)