@@ -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 }
@@ -3308,22 +3313,42 @@ impl Compiler {
33083313 self . make_closure ( type_params_code, bytecode:: MakeFunctionFlags :: empty ( ) ) ?;
33093314
33103315 // Call the closure
3316+ // Call expects stack: [callable, self_or_null, arg1, ..., argN]
33113317 if num_typeparam_args > 0 {
3318+ // Stack: [arg1, ..., argN, closure]
3319+ // Need: [closure, NULL, arg1, ..., argN]
3320+ emit ! ( self , Instruction :: PushNull ) ;
3321+ // Stack: [arg1, ..., argN, closure, NULL]
33123322 emit ! (
33133323 self ,
3314- Instruction :: Swap {
3315- index : ( num_typeparam_args + 1 ) as u32
3324+ Instruction :: Reverse {
3325+ amount : ( num_typeparam_args + 2 ) as u32
33163326 }
33173327 ) ;
3328+ // Stack: [NULL, closure, argN, ..., arg1]
3329+ emit ! ( self , Instruction :: Swap { index: 2 } ) ;
3330+ // Stack: [closure, NULL, argN, ..., arg1]
3331+ if num_typeparam_args > 1 {
3332+ emit ! (
3333+ self ,
3334+ Instruction :: Reverse {
3335+ amount: num_typeparam_args as u32
3336+ }
3337+ ) ;
3338+ }
3339+ // Stack: [closure, NULL, arg1, ..., argN]
33183340 emit ! (
33193341 self ,
3320- Instruction :: CallFunctionPositional {
3342+ Instruction :: Call {
33213343 nargs: num_typeparam_args as u32
33223344 }
33233345 ) ;
33243346 } else {
3325- // No arguments, just call the closure
3326- emit ! ( self , Instruction :: CallFunctionPositional { nargs: 0 } ) ;
3347+ // Stack: [closure]
3348+ emit ! ( self , Instruction :: PushNull ) ;
3349+ // Stack: [closure, NULL] - already correct layout
3350+ // Call pops: args (0), then self_or_null (NULL), then callable (closure)
3351+ emit ! ( self , Instruction :: Call { nargs: 0 } ) ;
33273352 }
33283353 }
33293354
@@ -3691,6 +3716,7 @@ impl Compiler {
36913716
36923717 // Generate class creation code
36933718 emit ! ( self , Instruction :: LoadBuildClass ) ;
3719+ emit ! ( self , Instruction :: PushNull ) ;
36943720
36953721 // Set up the class function with type params
36963722 let mut func_flags = bytecode:: MakeFunctionFlags :: empty ( ) ;
@@ -3720,24 +3746,30 @@ impl Compiler {
37203746 if let Some ( arguments) = arguments
37213747 && !arguments. keywords . is_empty ( )
37223748 {
3749+ let mut kwarg_names = vec ! [ ] ;
37233750 for keyword in & arguments. keywords {
37243751 if let Some ( name) = & keyword. arg {
3725- self . emit_load_const ( ConstantData :: Str {
3752+ kwarg_names . push ( ConstantData :: Str {
37263753 value : name. as_str ( ) . into ( ) ,
37273754 } ) ;
3755+ } else {
3756+ panic ! ( "keyword argument name must be set" ) ;
37283757 }
37293758 self . compile_expression ( & keyword. value ) ?;
37303759 }
3760+ self . emit_load_const ( ConstantData :: Tuple {
3761+ elements : kwarg_names,
3762+ } ) ;
37313763 emit ! (
37323764 self ,
3733- Instruction :: CallFunctionKeyword {
3765+ Instruction :: CallKw {
37343766 nargs: nargs
37353767 + u32 :: try_from( arguments. keywords. len( ) )
37363768 . expect( "too many keyword arguments" )
37373769 }
37383770 ) ;
37393771 } else {
3740- emit ! ( self , Instruction :: CallFunctionPositional { nargs } ) ;
3772+ emit ! ( self , Instruction :: Call { nargs } ) ;
37413773 }
37423774
37433775 // Return the created class
@@ -3748,10 +3780,12 @@ impl Compiler {
37483780
37493781 // Execute the type params function
37503782 self . make_closure ( type_params_code, bytecode:: MakeFunctionFlags :: empty ( ) ) ?;
3751- emit ! ( self , Instruction :: CallFunctionPositional { nargs: 0 } ) ;
3783+ emit ! ( self , Instruction :: PushNull ) ;
3784+ emit ! ( self , Instruction :: Call { nargs: 0 } ) ;
37523785 } else {
37533786 // Non-generic class: standard path
37543787 emit ! ( self , Instruction :: LoadBuildClass ) ;
3788+ emit ! ( self , Instruction :: PushNull ) ;
37553789
37563790 // Create class function with closure
37573791 self . make_closure ( class_code, bytecode:: MakeFunctionFlags :: empty ( ) ) ?;
@@ -3762,7 +3796,7 @@ impl Compiler {
37623796 } else {
37633797 CallType :: Positional { nargs : 2 }
37643798 } ;
3765- self . compile_normal_call ( call) ;
3799+ self . compile_call_with_self ( call) ;
37663800 }
37673801
37683802 // Step 4: Apply decorators and store (common to both paths)
@@ -3912,10 +3946,11 @@ impl Compiler {
39123946 // Stack: [..., __exit__]
39133947 // Call __exit__(None, None, None)
39143948 self . set_source_range ( with_range) ;
3949+ emit ! ( self , Instruction :: PushNull ) ;
39153950 self . emit_load_const ( ConstantData :: None ) ;
39163951 self . emit_load_const ( ConstantData :: None ) ;
39173952 self . emit_load_const ( ConstantData :: None ) ;
3918- emit ! ( self , Instruction :: CallFunctionPositional { nargs: 3 } ) ;
3953+ emit ! ( self , Instruction :: Call { nargs: 3 } ) ;
39193954 if is_async {
39203955 emit ! ( self , Instruction :: GetAwaitable ) ;
39213956 self . emit_load_const ( ConstantData :: None ) ;
@@ -6088,41 +6123,33 @@ impl Compiler {
60886123
60896124 fn compile_call ( & mut self , func : & Expr , args : & Arguments ) -> CompileResult < ( ) > {
60906125 // Method call: obj → LOAD_ATTR_METHOD → [method, self_or_null] → args → CALL_WITH_SELF
6091- // Regular call: func → args → CALL
6126+ // Regular call: func → PUSH_NULL → args → CALL_WITH_SELF
60926127 if let Expr :: Attribute ( ExprAttribute { value, attr, .. } ) = & func {
60936128 // Method call: compile object, then LOAD_ATTR_METHOD
60946129 // LOAD_ATTR_METHOD pushes [method, self_or_null] on stack
60956130 self . compile_expression ( value) ?;
60966131 let idx = self . name ( attr. as_str ( ) ) ;
60976132 emit ! ( self , Instruction :: LoadAttrMethod { idx } ) ;
6098- // Compile args, then use CallWithSelf which handles self_or_null
6133+ // Compile args, then use Call which handles self_or_null
60996134 let call = self . compile_call_inner ( 0 , args) ?;
61006135 self . compile_call_with_self ( call) ;
61016136 } else {
6102- // Regular call: just compile function and args
6137+ // Regular call: push func, then NULL for self_or_null slot
6138+ // Stack layout: [func, NULL, args...] - same as method call [func, self, args...]
61036139 self . compile_expression ( func) ?;
6140+ emit ! ( self , Instruction :: PushNull ) ;
61046141 let call = self . compile_call_inner ( 0 , args) ?;
6105- self . compile_normal_call ( call) ;
6142+ self . compile_call_with_self ( call) ;
61066143 }
61076144 Ok ( ( ) )
61086145 }
61096146
61106147 fn compile_call_with_self ( & mut self , ty : CallType ) {
61116148 match ty {
61126149 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 } )
6150+ emit ! ( self , Instruction :: Call { nargs } )
61246151 }
6125- CallType :: Keyword { nargs } => emit ! ( self , Instruction :: CallFunctionKeyword { nargs } ) ,
6152+ CallType :: Keyword { nargs } => emit ! ( self , Instruction :: CallKw { nargs } ) ,
61266153 CallType :: Ex { has_kwargs } => emit ! ( self , Instruction :: CallFunctionEx { has_kwargs } ) ,
61276154 }
61286155 }
@@ -6412,6 +6439,7 @@ impl Compiler {
64126439
64136440 // Create comprehension function with closure
64146441 self . make_closure ( code, bytecode:: MakeFunctionFlags :: empty ( ) ) ?;
6442+ emit ! ( self , Instruction :: PushNull ) ;
64156443
64166444 // Evaluate iterated item:
64176445 self . compile_expression ( & generators[ 0 ] . iter ) ?;
@@ -6425,7 +6453,7 @@ impl Compiler {
64256453 } ;
64266454
64276455 // Call just created <listcomp> function:
6428- emit ! ( self , Instruction :: CallFunctionPositional { nargs: 1 } ) ;
6456+ emit ! ( self , Instruction :: Call { nargs: 1 } ) ;
64296457 if is_async_list_set_dict_comprehension {
64306458 emit ! ( self , Instruction :: GetAwaitable ) ;
64316459 self . emit_load_const ( ConstantData :: None ) ;
@@ -6841,10 +6869,11 @@ impl Compiler {
68416869 match action {
68426870 UnwindAction :: With { is_async } => {
68436871 // compiler_call_exit_with_nones
6872+ emit ! ( self , Instruction :: PushNull ) ;
68446873 self . emit_load_const ( ConstantData :: None ) ;
68456874 self . emit_load_const ( ConstantData :: None ) ;
68466875 self . emit_load_const ( ConstantData :: None ) ;
6847- emit ! ( self , Instruction :: CallFunctionPositional { nargs: 3 } ) ;
6876+ emit ! ( self , Instruction :: Call { nargs: 3 } ) ;
68486877
68496878 if is_async {
68506879 emit ! ( self , Instruction :: GetAwaitable ) ;
0 commit comments