Skip to content

Commit 88a0c40

Browse files
committed
Swift: move hierarchy IPA logic to schema.py
1 parent c70f3d3 commit 88a0c40

File tree

4 files changed

+67
-69
lines changed

4 files changed

+67
-69
lines changed

swift/codegen/generators/cppgen.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,10 @@ def _get_class(self, name: str) -> cpp.Class:
8080
trap_name=trap_name,
8181
)
8282

83-
@functools.lru_cache(maxsize=None)
84-
def _is_ipa(self, name: str) -> bool:
85-
cls = self._classmap[name]
86-
return cls.ipa is not None or (
87-
cls.derived and all(self._is_ipa(d) for d in cls.derived))
88-
8983
def get_classes(self):
9084
ret = {'': []}
9185
for k, cls in self._classmap.items():
92-
if not self._is_ipa(k):
86+
if not cls.ipa:
9387
ret.setdefault(cls.group, []).append(self._get_class(cls.name))
9488
return ret
9589

swift/codegen/lib/schema/schema.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,32 @@ def _toposort_classes_by_group(classes: typing.Dict[str, Class]) -> typing.Dict[
247247
return ret
248248

249249

250+
def _fill_ipa_information(classes: typing.Dict[str, Class]):
251+
if not classes:
252+
return
253+
254+
is_ipa: typing.Dict[str, bool] = {}
255+
256+
def fill_is_ipa(name: str):
257+
if name not in is_ipa:
258+
cls = classes[name]
259+
for d in cls.derived:
260+
fill_is_ipa(d)
261+
if cls.ipa is not None:
262+
is_ipa[name] = True
263+
elif not cls.derived:
264+
is_ipa[name] = False
265+
else:
266+
is_ipa[name] = all(is_ipa[d] for d in cls.derived)
267+
268+
root = next(iter(classes))
269+
fill_is_ipa(root)
270+
271+
for name, cls in classes.items():
272+
if cls.ipa is None and is_ipa[name]:
273+
cls.ipa = IpaInfo()
274+
275+
250276
def load(m: types.ModuleType) -> Schema:
251277
includes = set()
252278
classes = {}
@@ -274,6 +300,8 @@ def load(m: types.ModuleType) -> Schema:
274300
null = name
275301
cls.is_null_class = True
276302

303+
_fill_ipa_information(classes)
304+
277305
return Schema(includes=includes, classes=_toposort_classes_by_group(classes), null=null)
278306

279307

swift/codegen/test/test_cppgen.py

Lines changed: 3 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -183,79 +183,22 @@ def test_cpp_skip_pragma(generate):
183183
def test_ipa_classes_ignored(generate):
184184
assert generate([
185185
schema.Class(
186-
name="X",
187-
ipa=schema.IpaInfo(from_class="A"),
188-
),
189-
schema.Class(
190-
name="Y",
191-
ipa=schema.IpaInfo(on_arguments={"a": "A", "b": "int"}),
192-
),
193-
schema.Class(
194-
name="Z",
195-
),
196-
]) == [
197-
cpp.Class(name="Z", final=True, trap_name="Zs"),
198-
]
199-
200-
201-
def test_ipa_hierarchy_ignored(generate):
202-
assert generate([
203-
schema.Class(
204-
name="Root",
205-
derived={"Base", "Z"},
206-
),
207-
schema.Class(
208-
name="Base",
209-
bases=["Root"],
210-
derived={"X", "Y"}
186+
name="W",
187+
ipa=schema.IpaInfo(),
211188
),
212189
schema.Class(
213190
name="X",
214-
bases=["Base"],
215-
ipa=schema.IpaInfo(from_class="A"),
216-
),
217-
schema.Class(
218-
name="Y",
219-
bases=["Base"],
220-
ipa=schema.IpaInfo(on_arguments={"a": "A", "b": "int"}),
221-
),
222-
schema.Class(
223-
name="Z",
224191
ipa=schema.IpaInfo(from_class="A"),
225192
),
226-
]) == []
227-
228-
229-
def test_ipa_hierarchy_not_ignored_with_non_ipa_descendant(generate):
230-
root = cpp.Class(name="Root")
231-
base = cpp.Class(name="Base", bases=[root])
232-
assert generate([
233-
schema.Class(
234-
name="Root",
235-
derived={"Base", "Z"},
236-
),
237-
schema.Class(
238-
name="Base",
239-
bases=["Root"],
240-
derived={"X", "Y"}
241-
),
242-
schema.Class(
243-
name="X",
244-
bases=["Base"],
245-
),
246193
schema.Class(
247194
name="Y",
248-
bases=["Base"],
249195
ipa=schema.IpaInfo(on_arguments={"a": "A", "b": "int"}),
250196
),
251197
schema.Class(
252198
name="Z",
253-
ipa=schema.IpaInfo(from_class="A"),
254199
),
255200
]) == [
256-
root,
257-
base,
258-
cpp.Class(name="X", bases=[base], final=True, trap_name="Xes"),
201+
cpp.Class(name="Z", final=True, trap_name="Zs"),
259202
]
260203

261204

swift/codegen/test/test_schema.py

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ class B(A):
340340
pass
341341

342342
assert data.classes == {
343-
'A': schema.Class('A', derived={'B'}),
343+
'A': schema.Class('A', derived={'B'}, ipa=schema.IpaInfo()),
344344
'B': schema.Class('B', bases=['A'], ipa=schema.IpaInfo(from_class="A")),
345345
}
346346

@@ -381,7 +381,7 @@ class B(A):
381381
pass
382382

383383
assert data.classes == {
384-
'A': schema.Class('A', derived={'B'}),
384+
'A': schema.Class('A', derived={'B'}, ipa=schema.IpaInfo()),
385385
'B': schema.Class('B', bases=['A'], ipa=schema.IpaInfo(on_arguments={'a': 'A', 'i': 'int'})),
386386
}
387387

@@ -414,6 +414,39 @@ class B:
414414
pass
415415

416416

417+
def test_ipa_class_hierarchy():
418+
@schema.load
419+
class data:
420+
class Root:
421+
pass
422+
423+
class Base(Root):
424+
pass
425+
426+
class Intermediate(Base):
427+
pass
428+
429+
@defs.synth.on_arguments(a=Base, i=defs.int)
430+
class A(Intermediate):
431+
pass
432+
433+
@defs.synth.from_class(Base)
434+
class B(Base):
435+
pass
436+
437+
class C(Root):
438+
pass
439+
440+
assert data.classes == {
441+
'Root': schema.Class('Root', derived={'Base', 'C'}),
442+
'Base': schema.Class('Base', bases=['Root'], derived={'Intermediate', 'B'}, ipa=schema.IpaInfo()),
443+
'Intermediate': schema.Class('Intermediate', bases=['Base'], derived={'A'}, ipa=schema.IpaInfo()),
444+
'A': schema.Class('A', bases=['Intermediate'], ipa=schema.IpaInfo(on_arguments={'a': 'Base', 'i': 'int'})),
445+
'B': schema.Class('B', bases=['Base'], ipa=schema.IpaInfo(from_class='Base')),
446+
'C': schema.Class('C', bases=['Root']),
447+
}
448+
449+
417450
def test_class_docstring():
418451
@schema.load
419452
class data:

0 commit comments

Comments
 (0)