forked from rose-compiler/rose
-
Notifications
You must be signed in to change notification settings - Fork 0
/
astDiff.C
112 lines (95 loc) · 5.56 KB
/
astDiff.C
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
// This code test two binary executable files for equivalence and
// reports the details of what is different when difference are
// detected in either the binary executable file format or the
// instruction stream.
// Traverse and add lables for the order of the visits to each node then
// build the vectors as pairs of elements (the node enum value and the
// the integer order of visit).
#include <rose.h>
#include <CommandLine.h>
#include <EditDistance/TreeEditDistance.h>
#include <Sawyer/CommandLine.h>
#include <Sawyer/Stopwatch.h>
using namespace std;
using namespace Rose;
// #include "labelTrace.h"
#include "treeIsomorphism.h"
#include "sequenceGeneration.h"
#include "treeEditDistance.h"
#include "commandLine.h"
// Parses only those switches that this tool recognizes and skips all others, leaving them for ROSE's frontend(). The tool
// switches come first and the ROSE switches are after a "--" separator switch. We wouldn't need to do it this way, but three
// things conspire to make this the best approach: (1) frontend() doesn't throw an error when it doesn't recognize a switch,
// (2) ROSE doesn't provide a description of its command-line, and (3) ROSE doesn't provide a mechanism to check the validity
// of a command line without actually applying it.
Sawyer::CommandLine::ParserResult
parseCommandLine(int argc, char *argv[], Settings &settings) {
using namespace Sawyer::CommandLine;
SwitchGroup gen = Rose::CommandLine::genericSwitches();
SwitchGroup tool = toolCommandLineSwitches(settings);
Parser parser;
parser
.purpose("demonstrates tree edit distance")
.doc("synopsis",
"@prop{programName} [@v{tool_switches}] -- [@v{rose_switches}] @v{specimen1} @v{specimen2}")
.doc("description",
"This tool performs tree edit distance between two source files a couple different ways in order to compare "
"the old, local implementation and the new librose implementation. See @s{use-old} for more details. The "
"output of the old implementation and the new implementation are not usually identical because there are "
"usually multiple edit paths with the same total cost.");
return parser.with(gen).with(tool).parse(argc, argv).apply();
}
int
main(int argc, char** argv)
{
ios::sync_with_stdio(); // Syncs C++ and C I/O subsystems!
ROSE_INITIALIZE;
Settings settings;
std::vector<std::string> roseArgs = parseCommandLine(argc, argv, settings).unreachedArgs();
roseArgs.insert(roseArgs.begin(), std::string(argv[0])); // not sure why frontend needs this, but it does.
SgProject* project = frontend(roseArgs);
ROSE_ASSERT (project != NULL);
// Internal AST consistancy tests.
AstTests::runAllTests(project);
ROSE_ASSERT(project->numberOfFiles() == 2);
int numberOfNodesInFile_0 = project->get_fileList()[0]->numberOfNodesInSubtree();
int numberOfNodesInFile_1 = project->get_fileList()[1]->numberOfNodesInSubtree();
printf ("numberOfNodesInFile_0 = %d \n",numberOfNodesInFile_0);
printf ("numberOfNodesInFile_1 = %d \n",numberOfNodesInFile_1);
if (settings.useOldImplementation) {
#if 0
diff(project->get_fileList()[0],project->get_fileList()[1]);
#else
vector< vector< SgNode* > > traversalTraceList = generateTraversalTraceList (project->get_fileList()[0],
project->get_fileList()[1],
/* minDepth = 0 */ 0,
/* infinite maxDepth */ -1 );
printf ("Calling sequenceAlignment()... traversalTraceList.size() = %zu \n",traversalTraceList.size());
sequenceAlignment ( traversalTraceList );
printf ("Done with call to sequenceAlignment() \n");
#endif
// This method simply prints the edits as a side effect and doesn't return anything useful.
Sawyer::Stopwatch tedLocalTimer;
tree_edit_distance (project->get_fileList()[0],project->get_fileList()[1]);
std::cout <<"local implementation of tree edit distance took " <<tedLocalTimer <<" seconds\n";
}
// This stuff uses the new edit distance analysis in librose
std::cout <<"Using TreeEditDistance from librose:\n";
EditDistance::TreeEditDistance::Analysis analysis;
Sawyer::Stopwatch tedRoseTimer;
analysis.compute(project->get_fileList()[0], project->get_fileList()[1], // the subtrees to compare
project->get_fileList()[0], project->get_fileList()[1]); // their file restrictions
std::cout <<"librose implementation of tree edit distance took " <<tedRoseTimer <<" seconds\n";
EditDistance::TreeEditDistance::Edits edits = analysis.edits();
std::cout <<" Nodes in source tree: " <<analysis.sourceTreeNodes().size() <<"\n"
<<" Nodes in target tree: " <<analysis.targetTreeNodes().size() <<"\n"
<<" Number of edits: " <<edits.size() <<"\n"
<<" Total cost of edits: " <<analysis.cost() <<"\n"
<<" Relative cost: " <<analysis.relativeCost() <<"\n"
<<" Individual edits:\n";
BOOST_FOREACH (const EditDistance::TreeEditDistance::Edit &edit, edits)
std::cout <<" " <<edit <<"\n";
std::ofstream graphViz("output-rose.dot");
analysis.emitGraphViz(graphViz);
std::cout <<"librose implementation of tree edit distance + output took " <<tedRoseTimer <<" seconds\n";
}