forked from usethesource/rascal-website
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
239 lines (193 loc) · 15.8 KB
/
index.html
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
---
layout: front
---
<h1>The one-stop shop for metaprogramming</h1>
<p class="lead">
You want to use the best tool for the job when analyzing, transforming or generating source code, so normally you will end up with many different tools, possibly even written in different languages.
Now the problem is to <strong>integrate</strong> these tools again. Rascal solves this problem by integrating source code analysis, transformation, and generation
primitives on the language level. Use it for any kind of metaprogramming task: to
construct parsers for programming languages, to analyze and transform source
code, or to define new DSLs with full IDE support.
</p>
<p class="lead">
Rascal is a programming language; such that meta programs
can be created by, understood by, and debugged by <strong>programmers</strong>.
</p>
<p class="lead">
Rascal <strong>primitives</strong> include immutable data, context-free grammars and algebraic data-types, relations, relational calculus operators,
advanced patterns matching, generic type-safe traversal, comprehensions, concrete syntax for objects, lexically scoped backtracking,
and string templates for code generation.
It has <strong>libraries</strong> for integrating language front-ends, for reusing analysis
algorithms, for getting typed meta-data out of
version management systems, for interactive visualization, etc.
</p>
<h2>Code snippets</h2>
<div class="tabbable">
<ul class="nav nav-tabs" id="Snippets">
<li class="active"><a href="#DSLs" data-toggle="tab">DSLs</a></li>
<li><a href="#Metrics" data-toggle="tab">Metrics</a></li>
<li><a href="#Transformations" data-toggle="tab">Transformations</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="DSLs">
<p>
From <a href="http://usethesource.io/dsl-in-36-lines-of-code">A DSL in 36 lines of code</a>:
</p>
<p>A grammar in Rascal:</p>
<pre class="rascal"><code><span class="Keyword">module</span> Syntax
<span class="Keyword">extend</span> lang::std::Layout;
<span class="Keyword">extend</span> lang::std::Id;
<span class="Keyword">start</span> <span class="Keyword">syntax</span> Machine = machine: State+ states;
<span class="Keyword">syntax</span> State = <span class="Comment">@Foldable</span> state: <span class="Constant">"state"</span> Id name Trans* out;
<span class="Keyword">syntax</span> Trans = trans: Id event <span class="Constant">":"</span> Id to;</code></pre>
<p>A fact extractor and checker in Rascal, using concrete syntax:</p>
<pre class="rascal"><code><span class="Keyword">module</span> Analyze
<span class="Keyword">import</span> Syntax;
<span class="Keyword">set</span>[Id] unreachable(Machine m) {
r = { <q1,q2> | (State)`<span class="Keyword">state</span> <span class="MetaVariable"><Id q1></span> <span class="MetaVariable"><Trans* ts></span>` <- m.states,
(Trans)`<span class="MetaVariable"><Id _></span>: <span class="MetaVariable"><Id q2></span>` <- ts }+;
qs = [ q.name | /State q := m ];
<span class="Keyword">return</span> { q | q <- qs, q <span class="Keyword">notin</span> r[qs[<span class="Keyword">0</span>]] };
}</code></pre>
<p>A code generator:</p>
<pre class="rascal"><code><span class="Keyword">module</span> Compile
<span class="Keyword">import</span> Syntax;
<span class="Keyword">str</span> compile(Machine m) =
<span class="Constant">"while (true) {
' event = input.next();
' switch (current) {
' <</span><span class="Keyword">for</span> (q <- m.states) {<span class="Constant">>
' case \"<</span>q.name<span class="Constant">>\":
' <</span><span class="Keyword">for</span> (t <- q.out) {<span class="Constant">>
' if (event.equals(\"<</span>t.event<span class="Constant">>\"))
' current = \"<</span>t.to<span class="Constant">>\";
' <</span>}<span class="Constant">>
' break;
' <</span>}<span class="Constant">>
' }
'}"</span>; </code></pre>
</div>
<div class="tab-pane" id="Metrics">
<h3>Finding the most complex methods in a set of Java files</h3>
<p>
We use Cyclomatic Complexity to measure the complexity of a method.
The first module implements a Cyclomatic Complexity calculation using
Concrete Syntax pattern matching.
</p>
<pre class="rascal"><code><span class="Keyword">module</span> CalculateCC
<span class="Keyword">import</span> lang::java::\syntax::Java15;
<span class="Keyword">int</span> cyclomaticComplexity(MethodDec m) {
result = 1;
<span class="Keyword">visit</span> (m) {
<span class="Keyword">case</span> (Stm)`<span class="Keyword">do</span> <span class="MetaVariable"><Stm _></span> <span class="Keyword">while</span> (<span class="MetaVariable"><Expr _></span>);`: result += 1;
<span class="Keyword">case</span> (Stm)`<span class="Keyword">while</span> (<span class="MetaVariable"><Expr _></span>) <span class="MetaVariable"><Stm _></span>`: result += 1;
<span class="Keyword">case</span> (Stm)`<span class="Keyword">if</span> (<span class="MetaVariable"><Expr _></span>) <span class="MetaVariable"><Stm _></span>`: result +=1;
<span class="Keyword">case</span> (Stm)`<span class="Keyword">if</span> (<span class="MetaVariable"><Expr _></span>) <span class="MetaVariable"><Stm _></span> <span class="Keyword">else</span> <span class="MetaVariable"><Stm _></span>`: result +=1;
<span class="Keyword">case</span> (Stm)`<span class="Keyword">for</span> (<span class="MetaVariable"><{Expr <span class="Constant">","</span>}* _></span>; <span class="MetaVariable"><Expr? _></span>; <span class="MetaVariable"><{Expr <span class="Constant">","</span>}*_></span>) <span class="MetaVariable"><Stm _></span>` : result += 1;
<span class="Keyword">case</span> (Stm)`<span class="Keyword">for</span> (<span class="MetaVariable"><LocalVarDec _></span> ; <span class="MetaVariable"><Expr? e></span> ; <span class="MetaVariable"><{Expr <span class="Constant">","</span>}* _></span>) <span class="MetaVariable"><Stm _></span>`: result += 1;
<span class="Keyword">case</span> (Stm)`<span class="Keyword">for</span> (<span class="MetaVariable"><FormalParam _></span> : <span class="MetaVariable"><Expr _></span>) <span class="MetaVariable"><Stm _></span>` : result += 1;
<span class="Keyword">case</span> (Stm)`<span class="Keyword">switch</span> (<span class="MetaVariable"><Expr _></span> ) <span class="MetaVariable"><SwitchBlock _></span>`: result += 1;
<span class="Keyword">case</span> (SwitchLabel)`<span class="Keyword">case</span> <span class="MetaVariable"><Expr _></span> :` : result += 1;
<span class="Keyword">case</span> (CatchClause)`<span class="Keyword">catch</span> (<span class="MetaVariable"><FormalParam _></span>) <span class="MetaVariable"><Block _></span>` : result += 1;
}
<span class="Keyword">return</span> result;
}</code></pre>
<p>
Then we iterate over all the files in a directory and it's sub directories
and select the top 10 most complex methods
</p>
<pre class="rascal"><code><span class="Keyword">module</span> FindComplexFiles
<span class="Keyword">import</span> List;
<span class="Keyword">import</span> Exception;
<span class="Keyword">import</span> ParseTree;
<span class="Keyword">import</span> util::FileSystem;
<span class="Keyword">import</span> lang::java::\syntax::Disambiguate;
<span class="Keyword">import</span> lang::java::\syntax::Java15;
<span class="Keyword">import</span> CalculateCC;
<span class="Keyword">lrel</span>[<span class="Keyword">int</span> cc, <span class="Keyword">loc</span> method] findComplexFiles(<span class="Keyword">loc</span> project, <span class="Keyword">int</span> limit = 10) {
result = [*maxCC(f) | /file(f) <- crawl(project), f.extension == <span class="Constant">"java"</span>];
result = sort(result, <span class="Keyword">bool</span> (<<span class="Keyword">int</span> a, <span class="Keyword">loc</span> _>, <<span class="Keyword">int</span> b, <span class="Keyword">loc</span> _>) { <span class="Keyword">return</span> a < b; });
<span class="Keyword">return</span> head(reverse(result), limit);
}
<span class="Keyword">set</span>[MethodDec] allMethods(<span class="Keyword">loc</span> file)
= {m | /MethodDec m := parse(#<span class="Keyword">start</span>[CompilationUnit], file)};
<span class="Keyword">lrel</span>[<span class="Keyword">int</span> cc, <span class="Keyword">loc</span> method] maxCC(<span class="Keyword">loc</span> file)
= [<cyclomaticComplexity(m), m@\loc> | m <- allMethods(file)];</code></pre>
<p>
Running <code>findComplex</code> on the JHotdraw project returns the
following top 10 complex methods
</p>
<pre class="pre-scrollable-x">
rascal>findComplexFiles(|project://jhotdraw751/|)
lrel[int cc,loc method]: [
<<span class="important">83</span>,|project://jhotdraw751/JHotDraw%207.5.1/Source/jhotdraw7/src/main/java/org/jhotdraw/io/StreamPosTokenizer.java|(17762,15910,<499,4>,<946,5>)>,
<<span class="important">42</span>,|project://jhotdraw751/JHotDraw%207.5.1/Source/jhotdraw7/src/main/java/org/jhotdraw/draw/liner/SlantedLiner.java|(1396,6337,<53,4>,<208,5>)>,
<<span class="important">42</span>,|project://jhotdraw751/JHotDraw%207.5.1/Source/jhotdraw7/src/main/java/org/jhotdraw/geom/BezierPath.java|(14900,4669,<486,4>,<634,5>)>,
<<span class="important">31</span>,|project://jhotdraw751/JHotDraw%207.5.1/Source/jhotdraw7/src/main/java/org/jhotdraw/draw/DefaultDrawingViewTransferHandler.java|(2659,12674,<75,4>,<297,5>)>,
<<span class="important">30</span>,|project://jhotdraw751/JHotDraw%207.5.1/Source/jhotdraw7/src/main/java/org/jhotdraw/draw/liner/ElbowLiner.java|(1422,5658,<52,4>,<186,5>)>,
<<span class="important">28</span>,|project://jhotdraw751/JHotDraw%207.5.1/Source/jhotdraw7/src/main/java/org/jhotdraw/color/HSLPhysiologicColorSpace.java|(1234,3094,<41,4>,<149,5>)>,
<<span class="important">28</span>,|project://jhotdraw751/JHotDraw%207.5.1/Source/jhotdraw7/src/main/java/org/jhotdraw/xml/JavaPrimitivesDOMFactory.java|(6035,3378,<175,4>,<263,5>)>,
<<span class="important">25</span>,|project://jhotdraw751/JHotDraw%207.5.1/Source/jhotdraw7/src/main/java/net/n3/nanoxml/StdXMLParser.java|(11928,7203,<460,3>,<657,4>)>,
<<span class="important">25</span>,|project://jhotdraw751/JHotDraw%207.5.1/Source/jhotdraw7/src/main/java/org/jhotdraw/xml/JavaPrimitivesDOMFactory.java|(9424,2954,<266,4>,<335,5>)>,
<<span class="important">24</span>,|project://jhotdraw751/JHotDraw%207.5.1/Source/jhotdraw7/src/main/java/org/jhotdraw/draw/liner/CurvedLiner.java|(1413,5993,<53,4>,<191,5>)>
]
</pre>
<p>
<code>|project...|</code> are source locations, which is a native concept in
Rascal.
Source locations represent a unique identifier for files (URI) along with a
specific region in a file.
</p>
<p>
Inside the Rascal IDE you can click on any of these source locations, and
an editor will open and show the file and the relevant range
</p>
</div>
<div class="tab-pane" id="Transformations">
<p>This is a very basic source-to-source Java transformation which changes the style of the code without changing its semantics. The code uses concrete syntax to make sure no syntax errors are introduced and to make sure the rules always match something that really exists in Java.</p>
<pre class="rascal"><code><span class="Keyword">module</span> Idiomatic
<span class="Keyword">import</span> lang::java::\syntax::Java15;
<span class="Keyword">import</span> IO;
<span class="Keyword">import</span> ParseTree;
CompilationUnit idiomatic(CompilationUnit unit) = <span class="Keyword">innermost</span> <span class="Keyword">visit</span>(unit) {
<span class="Keyword">case</span> (Stm) `<span class="Keyword">if</span> (!<span class="MetaVariable"><Expr cond></span>) <span class="MetaVariable"><Stm a></span> <span class="Keyword">else</span> <span class="MetaVariable"><Stm b></span>` =>
(Stm) `<span class="Keyword">if</span> (<span class="MetaVariable"><Expr cond></span>) <span class="MetaVariable"><Stm b></span> <span class="Keyword">else</span> <span class="MetaVariable"><Stm a></span>`
<span class="Keyword">case</span> (Stm) `<span class="Keyword">if</span> (<span class="MetaVariable"><Expr cond></span>) <span class="MetaVariable"><Stm a></span>` =>
(Stm) `<span class="Keyword">if</span> (<span class="MetaVariable"><Expr cond></span>) { <span class="MetaVariable"><Stm a></span> }`
<span class="Keyword">when</span> (Stm) `<span class="MetaVariable"><Block _></span>` !:= a
<span class="Keyword">case</span> (Stm) `<span class="Keyword">if</span> (<span class="MetaVariable"><Expr cond></span>) <span class="MetaVariable"><Stm a></span> <span class="Keyword">else</span> <span class="MetaVariable"><Stm b></span>` =>
(Stm) `<span class="Keyword">if</span> (<span class="MetaVariable"><Expr cond></span>) { <span class="MetaVariable"><Stm a></span> } <span class="Keyword">else</span> { <span class="MetaVariable"><Stm b></span> }`
<span class="Keyword">when</span> (Stm) `<span class="MetaVariable"><Block _></span>` !:= a
<span class="Keyword">case</span> (Stm) `<span class="Keyword">if</span> (<span class="MetaVariable"><Expr cond></span>) { <span class="Keyword">return</span> <span class="Keyword">true</span>; } <span class="Keyword">else</span> { <span class="Keyword">return</span> <span class="Keyword">false</span>; }` =>
(Stm) `<span class="Keyword">return</span> <span class="MetaVariable"><Expr cond></span>;`
};
</code></pre>
<p>The following code is a small test program written to demonstrate the effect of the idiomatic function. Test functions are integrated in Rascal and will generate random input for parameters and integrate with the IDE to produce test reports.</p>
<pre class="rascal"><code><span class="Keyword">test</span> <span class="Keyword">bool</span> example() {
code = (CompilationUnit) `<span class="Keyword">class</span> MyClass { <span class="Keyword">int</span> m() { <span class="Keyword">if</span> (!x) println("x"); <span class="Keyword">else</span> println("y"); <span class="Keyword">if</span> (x) <span class="Keyword">return</span> <span class="Keyword">true</span>; <span class="Keyword">else</span> <span class="Keyword">return</span> <span class="Keyword">false</span>; } }`;
<span class="Keyword">return</span> idiomatic(code)
==
(CompilationUnit) `<span class="Keyword">class</span> MyClass { <span class="Keyword">int</span> m() { <span class="Keyword">if</span> (x) { println("y"); } <span class="Keyword">else</span> { println("x"); } <span class="Keyword">return</span> x; } }` ;
}</code></pre>
</div>
</div>
</div>
<script src="assets/js/jquery-1.10.2.min.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var prefix = "_";
if (location.hash !== '') {
var target = 'a[href="' +location.hash.replace(prefix,"")+ '"]';
$(target).tab('show');
$('html,body').animate({scrollTop: $(target).offset().top - 40}, 'slow');
}
$('a[data-toggle="tab"]').on('shown', function(e) {
location.replace("#" + prefix + $(e.target).attr('href').substr(1));
});
});
$('#Snippets a').click(function (e) {
e.preventDefault();
$(this).tab('show');
})
</script>