rejuvenation_23.0.0_507c1f00/src/rejuvenation-match_patterns.ads

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
with Ada.Containers.Indefinite_Hashed_Maps;
with Ada.Strings; use Ada.Strings;
with Ada.Strings.Hash;

package Rejuvenation.Match_Patterns is

   type Match_Pattern is tagged private;
   --  The class Match_Pattern represents a single occurrence of an AST pattern
   --  in an AST instance. An AST pattern or AST instance is a list of physical
   --  AST nodes from Libadalang.
   --
   --  AST patterns are expressed as code snippets that can contain
   --  placeholders that can be mapped to AST nodes from the AST instance.
   --  If a placeholder occurs multiple times, then the string values of the
   --  mapped AST nodes must be identical.
   --
   --  To show diagnosis information about non-matches on the console, use:
   --    Rejuvenation.Match_Pattern.DIAGNOSE := True;

   -- Externally-visible data structures -------

   Inconsistent_Placeholder_Values_Exception : exception;
   --  Exception that indicates that a placeholder is assigned
   --  two different values.
   Unsupported_Placeholder_Exception : exception;
   --  Exception that indicates that an unsupported placeholder was observed.
   Invalid_Multiple_Placeholder_Status_Exception : exception;
   --  Internal programming error; this should not happen.

   DIAGNOSE : Boolean := False;
   --  Flag that indicates whether diagnosis information about non-matches is
   --  displayed on the console.

   -- Create match --------
   --  TODO: should order of parameters be in line with similar functions
   --        in Finder interface?
   function Match_Full
     (MP : out Match_Pattern; Pattern : Ada_Node; Instance : Ada_Node)
      return Boolean;
   --  Return whether the single-node AST pattern fully matches
   --  the single-node AST instance.
   --  If succesful, then the match attributes can afterwards be inspected.
   function Match_Full
     (MP       : out Match_Pattern; Pattern : Ada_Node_Array;
      Instance :     Ada_Node_Array) return Boolean;
   --  Return whether the node-array AST pattern fully matches
   --  the node-array AST instance.
   --  If succesful, then the match attributes can afterwards be inspected.
   function Match_Prefix
     (MP       : out Match_Pattern; Pattern : Ada_Node_Array;
      Instance :     Ada_Node_Array; Instance_Start_Index : Integer)
      return Boolean with
      Pre => Instance_Start_Index in Instance'Range;
      --  Return whether the node-array AST pattern matches
      --  a prefix of the node-array AST instance.
      --  If succesful, then the match attributes can afterwards be inspected.

   function Are_Identical
     (Node1 : Ada_Node'Class; Node2 : Ada_Node'Class) return Boolean;
   --  Return whether the ASTs of the two nodes match.
   --  Raises an exception if a placeholder pattern occurs.

   -- Inspect match --------

   function Get_Nodes (MP : Match_Pattern) return Node_List.Vector;
   --  Return the AST instance nodes that match with the AST pattern.

   --  TODO: Should we add an Is_Valid_Placeholder_Name function?

   function Has_Single
     (MP : Match_Pattern; Placeholder_Name : String) return Boolean;
   --  Return whether the "single" placeholder name is mapped
   --  to any AST node from the AST instance.
   function Get_Single_As_Node
     (MP : Match_Pattern; Placeholder_Name : String) return Ada_Node with
      Pre => Has_Single (MP, Placeholder_Name);
      --  Return the mapped AST node from the AST instance
      --  for the given "single" placeholder name.
   function Get_Single_As_Raw_Signature
     (MP : Match_Pattern; Placeholder_Name : String) return String with
      Pre => Has_Single (MP, Placeholder_Name);
      --  Return the mapped raw signature from the AST instance
      --  for the given "single" placeholder name.

   function Has_Multiple
     (MP : Match_Pattern; Placeholder_Name : String) return Boolean;
   --  Return whether the "multiple" placeholder name is mapped
   --  to any AST node from the AST instance.
   function Get_Multiple_As_Nodes
     (MP : Match_Pattern; Placeholder_Name : String)
      return Node_List.Vector with
      Pre => Has_Multiple (MP, Placeholder_Name);
      --  Return the mapped AST nodes from the AST instance
      --  for the given "multiple" placeholder name.
   function Get_Multiple_As_Raw_Signature
     (MP : Match_Pattern; Placeholder_Name : String) return String with
      Pre => Has_Multiple (MP, Placeholder_Name);
   --  Return the mapped raw signature from the AST instance
   --  for the given "multiple" placeholder name.
   --  Note this includes the separators and trivia (white spaces and comments)
   --  between the multiple nodes.

   function Get_Placeholder_As_Nodes
     (MP : Match_Pattern; Placeholder_Name : String) return Node_List.Vector;
   --  Return the mapped AST nodes from the AST instance
   --  for the given placeholder name (both single and multiple).
   function Get_Placeholder_As_Raw_Signature
     (MP : Match_Pattern; Placeholder_Name : String) return String;
   --  Return the mapped raw signature from the AST instance
   --  for the given placeholder name (both single and multiple).

private

   -- Create match --------

   function Has_Nested_Match_Full
     (MP : Match_Pattern; Pattern : Ada_Node; Instance : Ada_Node)
      return Boolean;
   function Match
     (MP       : in out Match_Pattern; Pattern : Ada_Node'Class;
      Instance :        Ada_Node'Class) return Boolean;
   function Match
     (MP : in out Match_Pattern; Pattern : Ada_Node_Array;
      Instance :        Ada_Node_Array; Instance_Start_Index : Integer;
      Pattern_Must_Cover_End_Of_Instance :    Boolean; Store_Nodes : Boolean)
      return Boolean with
      Pre => Instance'Last < Instance'First
      or else Instance_Start_Index in Instance'Range;
   function Match_Multiple_Placeholder
     (MP       : in out Match_Pattern; Pattern : Ada_Node'Class;
      Instance :        Ada_Node'Class) return Boolean;
   function Match_Single_Placeholder
     (MP       : in out Match_Pattern; Pattern : Ada_Node'Class;
      Instance :        Ada_Node'Class) return Boolean;
   function Match_Specific
     (MP       : in out Match_Pattern; Pattern : Ada_Node'Class;
      Instance :        Ada_Node'Class) return Boolean;

   procedure Dump_Partial_Match (MP : Match_Pattern);

   -- Internal data structures -------

   function Equivalent_Key (Left, Right : String) return Boolean;
   function Equivalent_Element (Left, Right : Ada_Node) return Boolean;
   function Equivalent_Element (Left, Right : Node_List.Vector) return Boolean;

   package Mapping_Single_Map is new Indefinite_Hashed_Maps
     (Key_Type => String, Element_Type => Ada_Node, Hash => Ada.Strings.Hash,
      Equivalent_Keys => Equivalent_Key, "=" => Equivalent_Element);

   package Mapping_Multiple_Map is new Indefinite_Hashed_Maps
     (Key_Type => String, Element_Type => Node_List.Vector,
      Hash     => Ada.Strings.Hash, Equivalent_Keys => Equivalent_Key,
      "="      => Equivalent_Element);

   type Match_Pattern is tagged record
      Nodes : Node_List.Vector;
      --  The AST instance nodes that match with the AST pattern.
      Mapping_Single : Mapping_Single_Map.Map;
      --  Mapping from "single" placeholder name to AST node.
      Mapping_Multiple : Mapping_Multiple_Map.Map;
      --  Mapping from "multiple" placeholder name to AST nodes.
   end record;

   type Multiple_Placeholder_Status is record
      Ongoing_Multiple          : Boolean  := False;
      Multiple_PlaceHolder_Name : Ada_Node := No_Ada_Node;
      --  TODO: Why called name and not node?
      Multiple_Placeholder_Nodes : Node_List.Vector;

      Has_Earlier_Multiple_Placeholder_Nodes : Boolean := False;
      Earlier_Multiple_Placeholder_Nodes     : Node_List.Vector;
   end record;

   function Is_Open (MPS : Multiple_Placeholder_Status) return Boolean;
   procedure Open
     (MPS : in out Multiple_Placeholder_Status; MP : Match_Pattern;
      Placeholder_Node :        Ada_Node);
   procedure Close
     (MPS : in out Multiple_Placeholder_Status; MP : in out Match_Pattern);
   procedure Update
     (MPS : in out Multiple_Placeholder_Status; Instance_Node : Ada_Node);

end Rejuvenation.Match_Patterns;