55from typing import Callable , Mapping , Tuple
66
77from mypyc .codegen .emit import Emitter , HeaderDeclaration , ReturnHandler
8- from mypyc .codegen .emitfunc import native_function_header , struct_type
8+ from mypyc .codegen .emitfunc import native_function_header
99from mypyc .codegen .emitwrapper import (
1010 generate_bin_op_wrapper ,
1111 generate_bool_wrapper ,
2121from mypyc .common import BITMAP_BITS , BITMAP_TYPE , NATIVE_PREFIX , PREFIX , REG_PREFIX
2222from mypyc .ir .class_ir import ClassIR , VTableEntries
2323from mypyc .ir .func_ir import FUNC_CLASSMETHOD , FUNC_STATICMETHOD , FuncDecl , FuncIR
24- from mypyc .ir .rtypes import RTuple , RType , object_rprimitive , RInstance
24+ from mypyc .ir .rtypes import RTuple , RType , object_rprimitive
2525from mypyc .namegen import NameGenerator
2626from mypyc .sametype import is_same_type
2727
@@ -294,7 +294,10 @@ def emit_line() -> None:
294294 # Declare setup method that allocates and initializes an object. type is the
295295 # type of the class being initialized, which could be another class if there
296296 # is an interpreted subclass.
297- emitter .emit_line (f"static PyObject *{ setup_name } (PyTypeObject *type);" )
297+ emitter .context .declarations [setup_name ] = HeaderDeclaration (
298+ f"PyObject *{ setup_name } (PyTypeObject *type);" , needs_export = True
299+ )
300+
298301 assert cl .ctor is not None
299302 emitter .emit_line (native_function_header (cl .ctor , emitter ) + ";" )
300303
@@ -397,13 +400,7 @@ def generate_object_struct(cl: ClassIR, emitter: Emitter) -> None:
397400
398401 for attr , rtype in base .attributes .items ():
399402 if (attr , rtype ) not in seen_attrs :
400- if isinstance (rtype , RInstance ) and rtype .class_ir .is_value_type :
401- # value types use structs directly
402- rtype_struct = struct_type (rtype .class_ir , emitter )
403- lines .append (f"{ emitter .ctype_spaced (rtype_struct )} { emitter .attr (attr )} ;" )
404- else :
405- lines .append (f"{ emitter .ctype_spaced (rtype )} { emitter .attr (attr )} ;" )
406-
403+ lines .append (f"{ emitter .ctype_spaced (rtype )} { emitter .attr (attr )} ;" )
407404 seen_attrs .add ((attr , rtype ))
408405
409406 if isinstance (rtype , RTuple ):
@@ -562,7 +559,7 @@ def generate_setup_for_class(
562559 emitter : Emitter ,
563560) -> None :
564561 """Generate a native function that allocates an instance of a class."""
565- emitter .emit_line ("static PyObject *" )
562+ emitter .emit_line ("PyObject *" )
566563 emitter .emit_line (f"{ func_name } (PyTypeObject *type)" )
567564 emitter .emit_line ("{" )
568565 emitter .emit_line (f"{ cl .struct_name (emitter .names )} *self;" )
@@ -593,7 +590,7 @@ def generate_setup_for_class(
593590
594591 # We don't need to set this field to NULL since tp_alloc() already
595592 # zero-initializes `self`.
596- if value != "NULL" :
593+ if value not in ( "NULL" , "0" ) :
597594 emitter .emit_line (rf"self->{ emitter .attr (attr )} = { value } ;" )
598595
599596 # Initialize attributes to default values, if necessary
@@ -622,10 +619,15 @@ def generate_constructor_for_class(
622619 """Generate a native function that allocates and initializes an instance of a class."""
623620 emitter .emit_line (f"{ native_function_header (fn , emitter )} " )
624621 emitter .emit_line ("{" )
625- emitter .emit_line (f"PyObject *self = { setup_name } ({ emitter .type_struct_name (cl )} );" )
626- emitter .emit_line ("if (self == NULL)" )
627- emitter .emit_line (" return NULL;" )
628- args = ", " .join (["self" ] + [REG_PREFIX + arg .name for arg in fn .sig .args ])
622+ if cl .is_value_type :
623+ emitter .emit_line (f"{ cl .struct_name (emitter .names )} self = {{0}};" )
624+ emitter .emit_line (f"self.vtable = { vtable_name } ;" )
625+ args = ", " .join (["(PyObject*)&self" ] + [REG_PREFIX + arg .name for arg in fn .sig .args ])
626+ else :
627+ emitter .emit_line (f"PyObject *self = { setup_name } ({ emitter .type_struct_name (cl )} );" )
628+ emitter .emit_line ("if (self == NULL)" )
629+ emitter .emit_line (" return NULL;" )
630+ args = ", " .join (["self" ] + [REG_PREFIX + arg .name for arg in fn .sig .args ])
629631 if init_fn is not None :
630632 emitter .emit_line (
631633 "char res = {}{}{}({});" .format (
@@ -636,17 +638,25 @@ def generate_constructor_for_class(
636638 )
637639 )
638640 emitter .emit_line ("if (res == 2) {" )
639- emitter .emit_line ("Py_DECREF(self);" )
640- emitter .emit_line ("return NULL;" )
641+ if cl .is_value_type :
642+ emitter .emit_line ("self.vtable = NULL;" )
643+ emitter .emit_line ("return self;" )
644+ else :
645+ emitter .emit_line ("Py_DECREF(self);" )
646+ emitter .emit_line ("return NULL;" )
641647 emitter .emit_line ("}" )
642648
643649 # If there is a nontrivial ctor that we didn't define, invoke it via tp_init
644650 elif len (fn .sig .args ) > 1 :
645651 emitter .emit_line (f"int res = { emitter .type_struct_name (cl )} ->tp_init({ args } );" )
646652
647653 emitter .emit_line ("if (res < 0) {" )
648- emitter .emit_line ("Py_DECREF(self);" )
649- emitter .emit_line ("return NULL;" )
654+ if cl .is_value_type :
655+ emitter .emit_line ("self.vtable = NULL;" )
656+ emitter .emit_line ("return self;" )
657+ else :
658+ emitter .emit_line ("Py_DECREF(self);" )
659+ emitter .emit_line ("return NULL;" )
650660 emitter .emit_line ("}" )
651661
652662 emitter .emit_line ("return self;" )
0 commit comments