uber / piranha

A tool for refactoring code related to feature flag APIs
Apache License 2.0
2.3k stars 198 forks source link

Better concrete syntax semantics #671

Closed danieltrt closed 4 months ago

danieltrt commented 5 months ago

Overview

This pull request introduces two significant changes to the semantics of the concrete syntax matching algorithm. These changes enhance the flexibility and expressiveness of the pattern matching with concrete syntax.

Change 1: Semantics of Template Variables :[var]

Previous Semantics

Previously, template variables :[var] could only match entire subtrees. This means it was not possible to match sequences of sibling nodes. For example, if matching [var] = 0; against int x = 0;, the match would fail because int and x are sibling nodes and not part of the same subtree.

graphviz-3

New Semantics

Now template variables can match multiple sequential siblings at the same level. So matching [var] = 0; with int x = 0; is possible.

graphviz-4

Change 2: Semantics of Matching Concrete Template

Previous Semantics

Previously, the algorithm required that the concrete template match an entire node, and only one node. This restriction limited the pattern matching to single statements rather than sequences of statements. For example:

int :[var] = 0;
:[var]++;

This template could never match, because it corresponds to two sibling nodes, rather than a single subtree. For example, the snippet

{
  int x = 0;
  x++;
  print(x);
}

has this tree representation.

graphviz-5

Notice that int x = 0; and x++; are sibling nodes. The template would never match just ONE node.

New Semantics

Now, the template can match entire sequential sibling nodes. This allows the template to match sequences of statements.

For example, the following code:

Code:

// just a regular loop in C++
int some = 0; 
while(some < 100) { 
    float length = 3.14;
    float area = length * length;
    some++; 
}
print(some);

matches the following template.

Template:

int :[var] = 0; 
while(:[var] < 100) { 
    :[body]

    :[var]++; 
}

and the alignment is as follow (loosely)

graphviz-6