33import textwrap
44from typing import List
55
6+ from mypy .build import BuildSource , build
7+ from mypy .errors import CompileError
8+ from mypy .options import Options
9+
10+ from mypyc import genops
611from mypyc .emitter import (
712 native_function_header ,
813 wrapper_function_header ,
914 CodeGenerator ,
1015)
1116from mypyc .common import PREFIX
12- from mypyc .ops import FuncIR
17+ from mypyc .ops import FuncIR , ClassIR , RTType
18+ from mypyc .refcount import insert_ref_count_opcodes
19+
20+
21+ def compile_module_to_c (sources : List [BuildSource ], module : str , options : Options ,
22+ alt_lib_path : str ) -> str :
23+ result = build (sources = sources ,
24+ options = options ,
25+ alt_lib_path = alt_lib_path )
26+ if result .errors :
27+ raise CompileError (result .errors )
1328
29+ functions , classes = genops .build_ir (result .files [module ], result .types )
30+ for fn in functions :
31+ insert_ref_count_opcodes (fn )
32+ return generate_c_module (module , functions , classes )
1433
15- def generate_c_module (name : str , fns : List [FuncIR ]) -> str :
34+
35+ def generate_c_module (name : str , fns : List [FuncIR ], classes : List [ClassIR ]) -> str :
1636 result = []
1737
38+ code_generator = CodeGenerator ()
39+
40+ for cl in classes :
41+ fragments = code_generator .generate_class_declaration (cl , name )
42+ result .extend (fragments )
43+
1844 for fn in fns :
1945 fragments = generate_function_declaration (fn )
2046 result .extend (fragments )
2147
2248 result .append ('' )
2349
24- code_generator = CodeGenerator ()
25-
26- fragments = generate_module_def (name , fns )
50+ fragments = generate_module_def (name , fns , classes )
2751 result .extend (fragments )
2852
2953 for fn in fns :
@@ -66,12 +90,18 @@ def generate_function_declaration(fn: FuncIR) -> List[str]:
6690
6791 PyMODINIT_FUNC PyInit_{name}(void)
6892 {{
69- return PyModule_Create(&module);
93+ PyObject *m;
94+ {init_classes}
95+ m = PyModule_Create(&module);
96+ if (m == NULL)
97+ return NULL;
98+ {namespace_setup}
99+ return m;
70100 }}
71101""" )
72102
73103
74- def generate_module_def (module_name : str , fns : List [FuncIR ]) -> List [str ]:
104+ def generate_module_def (module_name : str , fns : List [FuncIR ], classes : List [ ClassIR ] ) -> List [str ]:
75105 lines = []
76106 lines .append ('static PyMethodDef module_methods[] = {' )
77107 for fn in fns :
@@ -83,5 +113,22 @@ def generate_module_def(module_name: str, fns: List[FuncIR]) -> List[str]:
83113 lines .append (' {NULL, NULL, 0, NULL}' )
84114 lines .append ('};' )
85115 lines .append ('' )
86- lines .extend (init_func_format .format (name = module_name ).splitlines ())
116+
117+ init_classes = []
118+ namespace_setup = [] # type: List[str]
119+ for cl in classes :
120+ name = cl .name
121+ type_struct = '{}Type' .format (name )
122+ init_classes .extend (['{}.tp_new = PyType_GenericNew;' .format (type_struct ),
123+ ' if (PyType_Ready(&{}) < 0)' .format (type_struct ),
124+ ' return NULL;' ])
125+ namespace_setup .extend (
126+ ['Py_INCREF(&{});' .format (type_struct ),
127+ ' PyModule_AddObject(m, "{}", (PyObject *)&{});' .format (name , type_struct )])
128+
129+ lines .extend (
130+ init_func_format .format (
131+ name = module_name ,
132+ init_classes = '\n ' .join (init_classes ),
133+ namespace_setup = '\n ' .join (namespace_setup )).splitlines ())
87134 return lines
0 commit comments