From 05d5cd6ef0ba75be1eba2a44db2af063c132e514 Mon Sep 17 00:00:00 2001 From: Romain Beguet Date: Wed, 4 Oct 2023 12:03:51 +0200 Subject: [PATCH] Actually memoize previous_part and next_part. This improves performance further and doesn't really affect peak memory consumption. Because of eng/libadalang/langkit#710, overriden properties lose their memoization attribute. So, this change inlines the logic of the overriding properties inside the base properties to make sure memoization is applied. --- ada/ast.py | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/ada/ast.py b/ada/ast.py index 586ee1a04..729a43856 100644 --- a/ada/ast.py +++ b/ada/ast.py @@ -6921,12 +6921,18 @@ def previous_part(go_to_incomplete=(Bool, True)): """ Returns the previous part for this type decl. """ - return If( + return Cond( Self.is_generic_formal, # A generic formal type never has a previous part No(T.BaseTypeDecl.entity), + Self.is_a(ClasswideTypeDecl), + Entity.cast(ClasswideTypeDecl).type_decl + .previous_part(go_to_incomplete).then( + lambda pp: pp.classwide_type + ), + # Otherwise look for the previous part in the immediate enclosing # declarative region. Self.name.then( @@ -6976,6 +6982,18 @@ def next_part(): ) )), + lambda cwt=T.ClasswideTypeDecl: Let( + lambda td=cwt.type_decl: td.next_part.then( + # Sometimes `next_part` returns Entity itself, so check + # that to avoid an infinite loop. + lambda np: If( + td == np, + cwt, + np.classwide_type + ) + ) + ), + lambda _: If( Entity.is_private & Not(Entity.is_generic_formal), @@ -7384,26 +7402,6 @@ def discriminants_list( ): return Entity.type_decl.discriminants_list(stop_recurse_at) - @langkit_property(public=True, return_type=T.BaseTypeDecl.entity, - memoized=True) - def previous_part(go_to_incomplete=(Bool, True)): - return Entity.type_decl.previous_part(go_to_incomplete).then( - lambda pp: pp.classwide_type - ) - - @langkit_property() - def next_part(): - td = Var(Entity.type_decl) - return td.next_part.then( - # Sometimes `next_part` returns Entity itself, so check that - # to avoid an infinite loop. - lambda np: If( - td == np, - Entity, - np.classwide_type - ) - ) - canonical_type = Property(Entity.type_decl.canonical_type.then( # The canonical type should be classwide whenever it makes sense (e.g. # if the canonical type is a tagged record type.) Otherwise return