Generate a native function that allocates and initializes an instance of a class.
(
cl: ClassIR,
fn: FuncDecl,
init_fn: FuncIR | None,
setup_name: str,
vtable_name: str,
emitter: Emitter,
)
| 726 | |
| 727 | |
| 728 | def generate_constructor_for_class( |
| 729 | cl: ClassIR, |
| 730 | fn: FuncDecl, |
| 731 | init_fn: FuncIR | None, |
| 732 | setup_name: str, |
| 733 | vtable_name: str, |
| 734 | emitter: Emitter, |
| 735 | ) -> None: |
| 736 | """Generate a native function that allocates and initializes an instance of a class.""" |
| 737 | emitter.emit_line(f"{native_function_header(fn, emitter)}") |
| 738 | emitter.emit_line("{") |
| 739 | |
| 740 | fn_args = [REG_PREFIX + arg.name for arg in fn.sig.args] |
| 741 | type_arg = "(PyObject *)" + emitter.type_struct_name(cl) |
| 742 | new_args = ", ".join(fn_args) |
| 743 | |
| 744 | use_wrapper = ( |
| 745 | cl.has_method("__new__") |
| 746 | and len(fn.sig.args) == 2 |
| 747 | and fn.sig.args[0].kind == ARG_STAR |
| 748 | and fn.sig.args[1].kind == ARG_STAR2 |
| 749 | ) |
| 750 | emit_setup_or_dunder_new_call(cl, setup_name, type_arg, not use_wrapper, new_args, emitter) |
| 751 | |
| 752 | args = ", ".join(["self"] + fn_args) |
| 753 | if init_fn is not None: |
| 754 | call = ( |
| 755 | emitter.wrapper_function_call(init_fn.decl) |
| 756 | if use_wrapper |
| 757 | else emitter.native_function_call(init_fn.decl) |
| 758 | ) |
| 759 | cast = "!= NULL ? 0 : -1" if use_wrapper else "" |
| 760 | emitter.emit_line(f"char res = {call}({args}){cast};") |
| 761 | emitter.emit_line("if (res == 2) {") |
| 762 | emitter.emit_line("Py_DECREF(self);") |
| 763 | emitter.emit_line("return NULL;") |
| 764 | emitter.emit_line("}") |
| 765 | |
| 766 | # If there is a nontrivial ctor that we didn't define, invoke it via tp_init |
| 767 | elif len(fn.sig.args) > 1: |
| 768 | emitter.emit_line(f"int res = {emitter.type_struct_name(cl)}->tp_init({args});") |
| 769 | |
| 770 | emitter.emit_line("if (res < 0) {") |
| 771 | emitter.emit_line("Py_DECREF(self);") |
| 772 | emitter.emit_line("return NULL;") |
| 773 | emitter.emit_line("}") |
| 774 | |
| 775 | emitter.emit_line("return self;") |
| 776 | emitter.emit_line("}") |
| 777 | |
| 778 | |
| 779 | def generate_init_for_class(cl: ClassIR, init_fn: FuncIR, emitter: Emitter) -> str: |
no test coverage detected
searching dependent graphs…