@@ -286,21 +286,20 @@ def generate_bin_op_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str:
286
286
gen .emit_header ()
287
287
if fn .name not in reverse_op_methods and fn .name in reverse_op_method_names :
288
288
# There's only a reverse operator method.
289
- generate_bin_op_reverse_only_wrapper (cl , fn , emitter , gen )
289
+ generate_bin_op_reverse_only_wrapper (emitter , gen )
290
290
else :
291
291
rmethod = reverse_op_methods [fn .name ]
292
292
fn_rev = cl .get_method (rmethod )
293
293
if fn_rev is None :
294
294
# There's only a forward operator method.
295
- generate_bin_op_forward_only_wrapper (cl , fn , emitter , gen )
295
+ generate_bin_op_forward_only_wrapper (fn , emitter , gen )
296
296
else :
297
297
# There's both a forward and a reverse operator method.
298
298
generate_bin_op_both_wrappers (cl , fn , fn_rev , emitter , gen )
299
299
return wrapper_name
300
300
301
301
302
- def generate_bin_op_forward_only_wrapper (cl : ClassIR ,
303
- fn : FuncIR ,
302
+ def generate_bin_op_forward_only_wrapper (fn : FuncIR ,
304
303
emitter : Emitter ,
305
304
gen : 'WrapperGenerator' ) -> None :
306
305
gen .emit_arg_processing (error = GotoHandler ('typefail' ), raise_exception = False )
@@ -331,9 +330,7 @@ def generate_bin_op_forward_only_wrapper(cl: ClassIR,
331
330
gen .finish ()
332
331
333
332
334
- def generate_bin_op_reverse_only_wrapper (cl : ClassIR ,
335
- fn_rev : FuncIR ,
336
- emitter : Emitter ,
333
+ def generate_bin_op_reverse_only_wrapper (emitter : Emitter ,
337
334
gen : 'WrapperGenerator' ) -> None :
338
335
gen .arg_names = ['right' , 'left' ]
339
336
gen .emit_arg_processing (error = GotoHandler ('typefail' ), raise_exception = False )
@@ -650,47 +647,17 @@ def generate_wrapper_core(fn: FuncIR,
650
647
It converts the PyObject *s to the necessary types, checking and unboxing if necessary,
651
648
makes the call, then boxes the result if necessary and returns it.
652
649
"""
650
+ gen = WrapperGenerator (None , emitter )
651
+ gen .set_target (fn )
652
+ gen .arg_names = arg_names or [arg .name for arg in fn .args ]
653
+ gen .cleanups = cleanups or []
654
+ gen .optional_args = optional_args or []
655
+ gen .traceback_code = traceback_code or ''
653
656
654
- optional_args = optional_args or []
655
- cleanups = cleanups or []
656
- use_goto = bool (cleanups or traceback_code )
657
- error = ReturnHandler ('NULL' ) if not use_goto else GotoHandler ('fail' )
658
-
659
- arg_names = arg_names or [arg .name for arg in fn .args ]
660
- for arg_name , arg in zip (arg_names , fn .args ):
661
- # Suppress the argument check for *args/**kwargs, since we know it must be right.
662
- typ = arg .type if arg .kind not in (ARG_STAR , ARG_STAR2 ) else object_rprimitive
663
- generate_arg_check (arg_name ,
664
- typ ,
665
- emitter ,
666
- error ,
667
- optional = arg in optional_args )
668
- native_args = ', ' .join ('arg_{}' .format (arg ) for arg in arg_names )
669
- if fn .ret_type .is_unboxed or use_goto :
670
- # TODO: The Py_RETURN macros return the correct PyObject * with reference count handling.
671
- # Are they relevant?
672
- emitter .emit_line ('{}retval = {}{}({});' .format (emitter .ctype_spaced (fn .ret_type ),
673
- NATIVE_PREFIX ,
674
- fn .cname (emitter .names ),
675
- native_args ))
676
- emitter .emit_lines (* cleanups )
677
- if fn .ret_type .is_unboxed :
678
- emitter .emit_error_check ('retval' , fn .ret_type , 'return NULL;' )
679
- emitter .emit_box ('retval' , 'retbox' , fn .ret_type , declare_dest = True )
680
-
681
- emitter .emit_line ('return {};' .format ('retbox' if fn .ret_type .is_unboxed else 'retval' ))
682
- else :
683
- emitter .emit_line ('return {}{}({});' .format (NATIVE_PREFIX ,
684
- fn .cname (emitter .names ),
685
- native_args ))
686
- # TODO: Tracebacks?
687
-
688
- if use_goto :
689
- emitter .emit_label ('fail' )
690
- emitter .emit_lines (* cleanups )
691
- if traceback_code :
692
- emitter .emit_lines (traceback_code )
693
- emitter .emit_lines ('return NULL;' )
657
+ error = ReturnHandler ('NULL' ) if not gen .use_goto () else GotoHandler ('fail' )
658
+ gen .emit_arg_processing (error = error )
659
+ gen .emit_call ()
660
+ gen .emit_error_handling ()
694
661
695
662
696
663
def generate_arg_check (name : str ,
@@ -741,7 +708,7 @@ class WrapperGenerator:
741
708
742
709
# TODO: Use this for more wrappers
743
710
744
- def __init__ (self , cl : ClassIR , emitter : Emitter ) -> None :
711
+ def __init__ (self , cl : Optional [ ClassIR ] , emitter : Emitter ) -> None :
745
712
self .cl = cl
746
713
self .emitter = emitter
747
714
self .cleanups : List [str ] = []
@@ -764,7 +731,7 @@ def wrapper_name(self) -> str:
764
731
"""Return the name of the wrapper function."""
765
732
return '{}{}{}' .format (DUNDER_PREFIX ,
766
733
self .target_name ,
767
- self .cl .name_prefix (self .emitter .names ))
734
+ self .cl .name_prefix (self .emitter .names ) if self . cl else '' )
768
735
769
736
def use_goto (self ) -> bool :
770
737
"""Do we use a goto for error handling (instead of straight return)?"""
0 commit comments