Skip to content

Commit d70744d

Browse files
committed
Beginnings of compiling user-defined classes
Bunch of stuff is still not working.
1 parent 364d992 commit d70744d

12 files changed

Lines changed: 441 additions & 58 deletions

File tree

lib-rt/CPy.h

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,29 @@ extern "C" {
1010

1111
// Naming conventions:
1212
//
13-
// LongInt: tagged long int
14-
// ShortInt: tagged short int
15-
// CInt: C 'int' value
16-
// Int: tagged int (long or short)
17-
// Obj: CPython object (PyObject *)
13+
// Tagged: tagged int
14+
// Long: tagged long int (pointer)
15+
// Short: tagged short int (unboxed)
16+
// LongLong: C long long (64 bit)
17+
// Int: C int
18+
// Object: CPython object (PyObject *)
1819

1920
typedef unsigned long long CPyTagged;
2021
typedef long long CPySignedInt;
2122

2223
#define CPY_INT_TAG 1
2324

25+
typedef void (*CPyVTableItem)(void);
26+
27+
// Get attribute value using vtable (may return an undefined value)
28+
#define CPY_GET_ATTR(obj, vtable_index, object_type, attr_type) \
29+
(attr_type (*)(object_type *)((object_type *)obj)->vtable[vtable_index])((object_type *)obj)
30+
31+
// Set attribute value using vtable
32+
#define CPY_SET_ATTR(obj, vtable_index, value, object_type, attr_type) \
33+
(void (*)(object_type *, attr_type)((object_type *)obj)->vtable[vtable_index])( \
34+
(object_type *)obj, value);
35+
2436
inline int CPyTagged_CheckLong(CPyTagged x) {
2537
return x & CPY_INT_TAG;
2638
}

mypyc/compiler.py

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,51 @@
33
import textwrap
44
from 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
611
from mypyc.emitter import (
712
native_function_header,
813
wrapper_function_header,
914
CodeGenerator,
1015
)
1116
from 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

Comments
 (0)