(
cl: ClassIR, fn: FuncIR, fn_rev: FuncIR, emitter: Emitter, gen: WrapperGenerator
)
| 401 | |
| 402 | |
| 403 | def generate_bin_op_both_wrappers( |
| 404 | cl: ClassIR, fn: FuncIR, fn_rev: FuncIR, emitter: Emitter, gen: WrapperGenerator |
| 405 | ) -> None: |
| 406 | # There's both a forward and a reverse operator method. First |
| 407 | # check if we should try calling the forward one. If the |
| 408 | # argument type check fails, fall back to the reverse method. |
| 409 | # |
| 410 | # Similar to above, we can't perfectly match Python semantics. |
| 411 | # In regular Python code you'd return NotImplemented if the |
| 412 | # operand has the wrong type, but in compiled code we'll never |
| 413 | # get to execute the type check. |
| 414 | emitter.emit_line( |
| 415 | "if (PyObject_IsInstance(obj_left, (PyObject *){})) {{".format( |
| 416 | emitter.type_struct_name(cl) |
| 417 | ) |
| 418 | ) |
| 419 | gen.emit_arg_processing(error=GotoHandler("typefail"), raise_exception=False) |
| 420 | handle_third_pow_argument(fn, emitter, gen, if_unsupported=["goto typefail2;"]) |
| 421 | # Ternary __rpow__ calls aren't a thing so immediately bail |
| 422 | # if ternary __pow__ returns NotImplemented. |
| 423 | if fn.name == "__pow__" and len(fn.args) == 3: |
| 424 | fwd_not_implemented_handler = "goto typefail2;" |
| 425 | else: |
| 426 | fwd_not_implemented_handler = "goto typefail;" |
| 427 | gen.emit_call(not_implemented_handler=fwd_not_implemented_handler) |
| 428 | gen.emit_error_handling() |
| 429 | emitter.emit_line("}") |
| 430 | emitter.emit_label("typefail") |
| 431 | emitter.emit_line( |
| 432 | "if (PyObject_IsInstance(obj_right, (PyObject *){})) {{".format( |
| 433 | emitter.type_struct_name(cl) |
| 434 | ) |
| 435 | ) |
| 436 | gen.set_target(fn_rev) |
| 437 | gen.arg_names = ["right", "left"] |
| 438 | gen.emit_arg_processing(error=GotoHandler("typefail2"), raise_exception=False) |
| 439 | handle_third_pow_argument(fn_rev, emitter, gen, if_unsupported=["goto typefail2;"]) |
| 440 | gen.emit_call() |
| 441 | gen.emit_error_handling() |
| 442 | emitter.emit_line("} else {") |
| 443 | generate_bin_op_reverse_dunder_call(fn, emitter, fn_rev.name) |
| 444 | emitter.emit_line("}") |
| 445 | emitter.emit_label("typefail2") |
| 446 | emitter.emit_line("Py_INCREF(Py_NotImplemented);") |
| 447 | emitter.emit_line("return Py_NotImplemented;") |
| 448 | gen.finish() |
| 449 | |
| 450 | |
| 451 | def generate_bin_op_reverse_dunder_call(fn: FuncIR, emitter: Emitter, rmethod: str) -> None: |
no test coverage detected
searching dependent graphs…