Skip to content

Commit 1ebb873

Browse files
committed
Lkt lowering: handle the "unique" array method
TN: RA22-015
1 parent 1f09ded commit 1ebb873

File tree

3 files changed

+32
-11
lines changed

3 files changed

+32
-11
lines changed

contrib/lkt/language/parser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ def get_builtin_gen_decl(entity_name=T.Symbol):
199199
)
200200

201201
array_type = Property(
202-
Self.array_gen_type.decl.cast(T.TypeDecl), public=True,
202+
Self.array_gen_type.decl.cast(T.NamedTypeDecl), public=True,
203203
doc="Unit method. Return the array builtin type."
204204
)
205205

@@ -210,7 +210,7 @@ def get_builtin_gen_decl(entity_name=T.Symbol):
210210
)
211211

212212
astlist_type = Property(
213-
Self.astlist_gen_type.decl.cast(T.TypeDecl),
213+
Self.astlist_gen_type.decl.cast(T.NamedTypeDecl),
214214
public=True,
215215
doc="Unit method. Return the ASTList builtin type."
216216
)

langkit/lkt_lowering.py

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,17 @@ def check_referenced_decl(expr: L.Expr) -> L.Decl:
7272
assert False, f"Cannot get referenced decl for {expr}: {exc}"
7373

7474

75+
def same_node(left: L.LKNode, right: L.LKNode) -> bool:
76+
"""
77+
Return whether ``left`` and ``right`` designate the same node, regardless
78+
of generic instantiation information.
79+
80+
.. todo:: This should probably belong to Liblktlang, in one form or
81+
another. See use cases.
82+
"""
83+
return left.unit == right.unit and left.sloc_range == right.sloc_range
84+
85+
7586
def pattern_as_str(str_lit: Union[L.StringLit, L.TokenPatternLit]) -> str:
7687
"""
7788
Return the regexp string associated to this string literal node.
@@ -1144,7 +1155,7 @@ def __init__(self, ctx: CompileCtx, lkt_units: List[L.AnalysisUnit]):
11441155

11451156
root = lkt_units[0].root
11461157

1147-
def get_field(decl: L.TraitDecl, name: str) -> L.Decl:
1158+
def get_field(decl: L.NamedTypeDecl, name: str) -> L.Decl:
11481159
"""
11491160
Return the (assumed existing and unique) declaration called
11501161
``name`` nested in ``decl``.
@@ -1160,9 +1171,11 @@ def get_field(decl: L.TraitDecl, name: str) -> L.Decl:
11601171
self.array_type = root.p_array_type
11611172
self.astlist_type = root.p_astlist_type
11621173
self.iterator_trait = root.p_iterator_trait
1163-
self.map_method = get_field(self.iterator_trait, 'map')
11641174
self.analysis_unit_trait = root.p_analysis_unit_trait
11651175

1176+
self.map_method = get_field(self.iterator_trait, 'map')
1177+
self.unique_method = get_field(self.array_type, 'unique')
1178+
11661179
# Map Lkt nodes for the declarations of builtin types to the
11671180
# corresponding CompiledType instances.
11681181
self.compiled_types = {
@@ -1475,12 +1488,7 @@ def lower_args() -> Tuple[List[AbstractExpression],
14751488
assert not args
14761489
return E.New(struct_type, **kwargs)
14771490

1478-
# TODO: change liblktlang so that we get an object similar to
1479-
# InstantiatedGenericType, and have an easy way to check it's
1480-
# the builtin map function.
1481-
elif (name_decl.unit, name_decl.sloc_range) == (
1482-
self.map_method.unit, self.map_method.sloc_range
1483-
):
1491+
elif same_node(name_decl, self.map_method):
14841492
# Build variable for iteration variables from the lambda
14851493
# expression arguments.
14861494
assert len(call_expr.f_args) == 1
@@ -1507,6 +1515,19 @@ def lower_args() -> Tuple[List[AbstractExpression],
15071515
element_var, index_var)
15081516
return result
15091517

1518+
elif same_node(name_decl, self.unique_method):
1519+
# Lower the prefix (the array to copy)
1520+
prefix = lower(expr.f_name)
1521+
1522+
# Defensive programming: make sure we have no arguments to
1523+
# lower.
1524+
args, kwargs = lower_args()
1525+
assert not args and not kwargs
1526+
1527+
# ".unique" works with our auto_attr magic: not worth type
1528+
# checking until we get rid of the syntax magic.
1529+
return prefix.unique # type: ignore
1530+
15101531
else:
15111532
# Otherwise, this call must be a method invocation. Note
15121533
# that not all methods map to actual field access in the

testsuite/tests/properties/unique/test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@ def test(a=T.AnalysisUnit.array):
2121

2222

2323
build_and_run(lkt_file='expected_concrete_syntax.lkt', py_script='main.py',
24-
lkt_semantic_checks=True)
24+
types_from_lkt=True)
2525
print('Done')

0 commit comments

Comments
 (0)