├── LICENSE
├── Makefile
├── README.md
├── demos
├── d8-3404-d8-8424.html
├── d8-3404.cc
├── d8-8424.cc
├── demo1-demo2.html
├── demo1.html
├── demo1.yin
├── demo2.html
├── demo2.yin
├── diff-s.css
├── diff.css
├── diff1-diff2.html
├── diff1.rkt
├── diff2.rkt
├── ikarus1.ss
├── ikarus2.ss
├── mk1.ss
├── mk2.ss
├── paredit20-paredit22.html
├── paredit20.el
├── paredit22-paredit23.html
├── paredit22.el
├── paredit23.el
├── pass1-pass2.html
├── simulator-arm.cc
├── simulator-mips-simulator-arm.html
├── simulator-mips.cc
├── typed-clojure1-typed-clojure2.html
├── typed-clojure1.clj
└── typed-clojure2.clj
├── diff-cpp.rkt
├── diff-js.rkt
├── diff-lisp.rkt
├── diff-yin.rkt
├── diff.css
├── diff.rkt
├── htmlize.rkt
├── nav.js
├── parse-cpp.rkt
├── parse-js.rkt
├── parse-lisp.rkt
├── parse-yin.rkt
├── parsec.rkt
├── structs.rkt
└── utils.rkt
/Makefile:
--------------------------------------------------------------------------------
1 | all:
2 | raco exe diff-lisp.rkt
3 | raco exe diff-cpp.rkt
4 | raco exe diff-js.rkt
5 | raco exe diff-yin.rkt
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ydiff
2 | =======
3 |
4 | *a structural comparison tool for Lisp programs*
5 |
6 |
7 | ### Demo
8 |
9 |
10 |
11 | ### Features
12 |
13 | * _Language-aware_. ydiff parses programs, understands basic language constructs and will not make non-sensical comparisons. For example it will not compare a string "10000" with an integer 10000 even though they look very similar. Also, it tries to match functions with the same name before it attempts to destruct and compare functions of different names.
14 |
15 | * _Format insensitive_. The comparison result will not be affected by different number of white spaces, line breaks or indentation. For example, ydiff will not produce a large diff just because you surrounded a block of code with if (condition) {...}.
16 |
17 | * _Moved code detection_. ydiff can find refactored code -- renamed, moved, reordered, wrapped, lifted, combined or fragmented code. Refactored code can be detected however deep they are into the structures.
18 |
19 | * _Human-friendly output_. The output of ydiff is designed for human understanding. The interactive UI helps the user navigate and understand changes efficiently.
20 |
21 |
22 | ### No longer supported Languages
23 |
24 | ydiff originally aim to support multiple languages, but I found that the parsers
25 | are very boring and tedious to get right. I hate languages with complicated
26 | syntax which makes parsing hard, so I decided to stop developing parsers for
27 | languages except the Lisp family. The C++ parser here is just to demonstrate how
28 | a mostly-right C++ can be constructed within two days of work ;-) You are
29 | welcome to take the code and extend to complete parsing C++ and JavaScript, but
30 | I can't provide any assistance.
31 |
32 |
33 | ### Installation
34 |
35 | ydiff is implemented in Racket. You can get Racket from
36 |
37 | http://racket-lang.org
38 |
39 | To build ydiff, go to the directory containing the source and run
40 |
41 | make
42 |
43 | It should compile to several executables, such as `diff-lisp`,
44 | `diff-cpp`, `diff-js` etc. Copy those files to some directory in your
45 | PATH.
46 |
47 |
48 |
49 | ### Usage
50 |
51 | 1. Run commands like this example:
52 |
53 | diff-lisp demos/mk1.ss demos/mk2.ss
54 |
55 | It will produce a HTML file named "mk1-mk2.html" in the current
56 | directory.
57 |
58 |
59 | 2. Use your browser to open the HTML file. That is basically it.
60 |
61 |
62 |
63 | ### Caveats
64 |
65 |
66 | 1. The HTML file needs the support files `nav.js` and `diff.css` to be
67 | present in the same directory. You must copy those files to the
68 | directory where you ran the commands. This is not a good user
69 | experience design and may be improved later.
70 |
71 |
72 |
73 | ### Contact
74 |
75 | Yin Wang (yinwang0@gmail.com)
76 |
77 |
78 |
79 | #### License (GPLv3)
80 |
81 | ydiff - a structural comparison tool for Lisp programs
82 |
83 | Copyright (c) 2011-2014 Yin Wang
84 |
85 | This program is free software: you can redistribute it and/or modify
86 | it under the terms of the GNU General Public License as published by
87 | the Free Software Foundation, either version 3 of the License, or
88 | (at your option) any later version.
89 |
90 | This program is distributed in the hope that it will be useful,
91 | but WITHOUT ANY WARRANTY; without even the implied warranty of
92 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
93 | GNU General Public License for more details.
94 |
95 | You should have received a copy of the GNU General Public License
96 | along with this program. If not, see .
97 |
--------------------------------------------------------------------------------
/demos/d8-3404.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2009 the V8 project authors. All rights reserved.
2 | // Redistribution and use in source and binary forms, with or without
3 | // modification, are permitted provided that the following conditions are
4 | // met:
5 | //
6 | // * Redistributions of source code must retain the above copyright
7 | // notice, this list of conditions and the following disclaimer.
8 | // * Redistributions in binary form must reproduce the above
9 | // copyright notice, this list of conditions and the following
10 | // disclaimer in the documentation and/or other materials provided
11 | // with the distribution.
12 | // * Neither the name of Google Inc. nor the names of its
13 | // contributors may be used to endorse or promote products derived
14 | // from this software without specific prior written permission.
15 | //
16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 |
28 |
29 | #include
30 | #include
31 |
32 | #include "d8.h"
33 | #include "d8-debug.h"
34 | #include "debug.h"
35 | #include "api.h"
36 | #include "natives.h"
37 | #include "platform.h"
38 |
39 |
40 | namespace v8 {
41 |
42 |
43 | const char* Shell::kHistoryFileName = ".d8_history";
44 | const char* Shell::kPrompt = "d8> ";
45 |
46 |
47 | LineEditor *LineEditor::first_ = NULL;
48 |
49 |
50 | LineEditor::LineEditor(Type type, const char* name)
51 | : type_(type),
52 | name_(name),
53 | next_(first_) {
54 | first_ = this;
55 | }
56 |
57 |
58 | LineEditor* LineEditor::Get() {
59 | LineEditor* current = first_;
60 | LineEditor* best = current;
61 | while (current != NULL) {
62 | if (current->type_ > best->type_)
63 | best = current;
64 | current = current->next_;
65 | }
66 | return best;
67 | }
68 |
69 |
70 | class DumbLineEditor: public LineEditor {
71 | public:
72 | DumbLineEditor() : LineEditor(LineEditor::DUMB, "dumb") { }
73 | virtual i::SmartPointer Prompt(const char* prompt);
74 | };
75 |
76 |
77 | static DumbLineEditor dumb_line_editor;
78 |
79 |
80 | i::SmartPointer DumbLineEditor::Prompt(const char* prompt) {
81 | static const int kBufferSize = 256;
82 | char buffer[kBufferSize];
83 | printf("%s", prompt);
84 | char* str = fgets(buffer, kBufferSize, stdin);
85 | return i::SmartPointer(str ? i::StrDup(str) : str);
86 | }
87 |
88 |
89 | CounterMap* Shell::counter_map_;
90 | i::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
91 | CounterCollection Shell::local_counters_;
92 | CounterCollection* Shell::counters_ = &local_counters_;
93 | Persistent Shell::utility_context_;
94 | Persistent Shell::evaluation_context_;
95 |
96 |
97 | bool CounterMap::Match(void* key1, void* key2) {
98 | const char* name1 = reinterpret_cast(key1);
99 | const char* name2 = reinterpret_cast(key2);
100 | return strcmp(name1, name2) == 0;
101 | }
102 |
103 |
104 | // Converts a V8 value to a C string.
105 | const char* ToCString(const v8::String::Utf8Value& value) {
106 | return *value ? *value : "";
107 | }
108 |
109 |
110 | // Executes a string within the current v8 context.
111 | bool Shell::ExecuteString(Handle source,
112 | Handle name,
113 | bool print_result,
114 | bool report_exceptions) {
115 | HandleScope handle_scope;
116 | TryCatch try_catch;
117 | if (i::FLAG_debugger) {
118 | // When debugging make exceptions appear to be uncaught.
119 | try_catch.SetVerbose(true);
120 | }
121 | Handle")
177 | (line port "")
178 | (line port "")))
179 |
180 |
181 |
182 | (define html-footer
183 | (lambda (port)
184 | (line port "")
185 | (line port "