@@ -72,6 +72,17 @@ def check_referenced_decl(expr: L.Expr) -> L.Decl:
72
72
assert False , f"Cannot get referenced decl for { expr } : { exc } "
73
73
74
74
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
+
75
86
def pattern_as_str (str_lit : Union [L .StringLit , L .TokenPatternLit ]) -> str :
76
87
"""
77
88
Return the regexp string associated to this string literal node.
@@ -1144,7 +1155,7 @@ def __init__(self, ctx: CompileCtx, lkt_units: List[L.AnalysisUnit]):
1144
1155
1145
1156
root = lkt_units [0 ].root
1146
1157
1147
- def get_field (decl : L .TraitDecl , name : str ) -> L .Decl :
1158
+ def get_field (decl : L .NamedTypeDecl , name : str ) -> L .Decl :
1148
1159
"""
1149
1160
Return the (assumed existing and unique) declaration called
1150
1161
``name`` nested in ``decl``.
@@ -1160,9 +1171,11 @@ def get_field(decl: L.TraitDecl, name: str) -> L.Decl:
1160
1171
self .array_type = root .p_array_type
1161
1172
self .astlist_type = root .p_astlist_type
1162
1173
self .iterator_trait = root .p_iterator_trait
1163
- self .map_method = get_field (self .iterator_trait , 'map' )
1164
1174
self .analysis_unit_trait = root .p_analysis_unit_trait
1165
1175
1176
+ self .map_method = get_field (self .iterator_trait , 'map' )
1177
+ self .unique_method = get_field (self .array_type , 'unique' )
1178
+
1166
1179
# Map Lkt nodes for the declarations of builtin types to the
1167
1180
# corresponding CompiledType instances.
1168
1181
self .compiled_types = {
@@ -1475,12 +1488,7 @@ def lower_args() -> Tuple[List[AbstractExpression],
1475
1488
assert not args
1476
1489
return E .New (struct_type , ** kwargs )
1477
1490
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 ):
1484
1492
# Build variable for iteration variables from the lambda
1485
1493
# expression arguments.
1486
1494
assert len (call_expr .f_args ) == 1
@@ -1507,6 +1515,19 @@ def lower_args() -> Tuple[List[AbstractExpression],
1507
1515
element_var , index_var )
1508
1516
return result
1509
1517
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
+
1510
1531
else :
1511
1532
# Otherwise, this call must be a method invocation. Note
1512
1533
# that not all methods map to actual field access in the
0 commit comments