mirah 0.0.4-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +15 -0
- data/README.txt +51 -0
- data/Rakefile +86 -0
- data/bin/duby +10 -0
- data/bin/dubyc +10 -0
- data/bin/dubyp +10 -0
- data/bin/jrubyp +36 -0
- data/bin/mirah +9 -0
- data/bin/mirah.cmd +1 -0
- data/bin/mirahc +9 -0
- data/bin/mirahc.cmd +1 -0
- data/bin/mirahp +9 -0
- data/bin/mirahp.cmd +1 -0
- data/examples/ant/example-build.xml +7 -0
- data/examples/appengine/Rakefile +19 -0
- data/examples/appengine/Readme +29 -0
- data/examples/appengine/src/org/mirah/MirahApp.mirah +57 -0
- data/examples/appengine/src/org/mirah/list.dhtml +15 -0
- data/examples/appengine/war/WEB-INF/lib/dubydatastore.jar +0 -0
- data/examples/bintrees.mirah +66 -0
- data/examples/construction.mirah +8 -0
- data/examples/dynamic.mirah +17 -0
- data/examples/edb.mirah +3 -0
- data/examples/fib.mirah +16 -0
- data/examples/fields.mirah +22 -0
- data/examples/fractal.mirah +55 -0
- data/examples/java_thing.mirah +13 -0
- data/examples/plugins/appengine/Rakefile +55 -0
- data/examples/plugins/appengine/lib/com/google/appengine/ext/duby/db/datastore.rb +375 -0
- data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/Model.duby +336 -0
- data/examples/plugins/appengine/test/com/google/appengine/ext/duby/db/ModelTest.duby +113 -0
- data/examples/simple_class.mirah +12 -0
- data/examples/sort_closure.mirah +7 -0
- data/examples/swing.mirah +20 -0
- data/examples/tak.mirah +15 -0
- data/examples/test.edb +9 -0
- data/examples/wiki/Rakefile +18 -0
- data/examples/wiki/src/org/mirah/wiki/MirahWiki.duby +324 -0
- data/examples/wiki/src/org/mirah/wiki/edit.eduby.html +42 -0
- data/examples/wiki/src/org/mirah/wiki/error.eduby.html +2 -0
- data/examples/wiki/src/org/mirah/wiki/layout.eduby.html +69 -0
- data/examples/wiki/src/org/mirah/wiki/parser.eduby.html +7 -0
- data/examples/wiki/src/org/mirah/wiki/view.eduby.html +15 -0
- data/examples/wiki/war/WEB-INF/classes/test/HeredocContext.class +0 -0
- data/examples/wiki/war/WEB-INF/classes/test/MirahParser.class +0 -0
- data/examples/wiki/war/WEB-INF/lib/appengine-api.jar +0 -0
- data/examples/wiki/war/WEB-INF/lib/dubydatastore.jar +0 -0
- data/examples/wiki/war/WEB-INF/lib/jmeta-runtime.jar +0 -0
- data/examples/wiki/war/WEB-INF/lib/pegdown-stubs.jar +0 -0
- data/examples/wiki/war/WEB-INF/pegdown.jar +0 -0
- data/examples/wiki/war/app.yaml +21 -0
- data/examples/wiki/war/public/favicon.ico +0 -0
- data/examples/wiki/war/public/images/appengine_duby.png +0 -0
- data/examples/wiki/war/public/images/back.gif +0 -0
- data/examples/wiki/war/public/images/dir.gif +0 -0
- data/examples/wiki/war/public/images/file.gif +0 -0
- data/examples/wiki/war/public/javascripts/prettify.js +61 -0
- data/examples/wiki/war/public/robots.txt +0 -0
- data/examples/wiki/war/public/stylesheets/main.css +156 -0
- data/examples/wiki/war/public/stylesheets/prettify.css +1 -0
- data/examples/wiki/war/public/stylesheets/sh_style.css +66 -0
- data/examples/wiki/war/public/stylesheets/source.css +21 -0
- data/examples/wiki/war/public/wmd/images/bg-fill.png +0 -0
- data/examples/wiki/war/public/wmd/images/bg.png +0 -0
- data/examples/wiki/war/public/wmd/images/blockquote.png +0 -0
- data/examples/wiki/war/public/wmd/images/bold.png +0 -0
- data/examples/wiki/war/public/wmd/images/code.png +0 -0
- data/examples/wiki/war/public/wmd/images/h1.png +0 -0
- data/examples/wiki/war/public/wmd/images/hr.png +0 -0
- data/examples/wiki/war/public/wmd/images/img.png +0 -0
- data/examples/wiki/war/public/wmd/images/italic.png +0 -0
- data/examples/wiki/war/public/wmd/images/link.png +0 -0
- data/examples/wiki/war/public/wmd/images/ol.png +0 -0
- data/examples/wiki/war/public/wmd/images/redo.png +0 -0
- data/examples/wiki/war/public/wmd/images/separator.png +0 -0
- data/examples/wiki/war/public/wmd/images/ul.png +0 -0
- data/examples/wiki/war/public/wmd/images/undo.png +0 -0
- data/examples/wiki/war/public/wmd/images/wmd-on.png +0 -0
- data/examples/wiki/war/public/wmd/images/wmd.png +0 -0
- data/examples/wiki/war/public/wmd/showdown.js +421 -0
- data/examples/wiki/war/public/wmd/wmd-base.js +1799 -0
- data/examples/wiki/war/public/wmd/wmd-plus.js +311 -0
- data/examples/wiki/war/public/wmd/wmd.js +73 -0
- data/javalib/JRubyParser.jar +0 -0
- data/javalib/dynalang-invoke-0.1.jar +0 -0
- data/javalib/mirah-bootstrap.jar +0 -0
- data/javalib/mirah-parser.jar +0 -0
- data/lib/duby.rb +2 -0
- data/lib/mirah.rb +338 -0
- data/lib/mirah/appengine_tasks.rb +146 -0
- data/lib/mirah/ast.rb +615 -0
- data/lib/mirah/ast/call.rb +307 -0
- data/lib/mirah/ast/class.rb +311 -0
- data/lib/mirah/ast/flow.rb +364 -0
- data/lib/mirah/ast/intrinsics.rb +470 -0
- data/lib/mirah/ast/literal.rb +154 -0
- data/lib/mirah/ast/local.rb +89 -0
- data/lib/mirah/ast/method.rb +360 -0
- data/lib/mirah/ast/scope.rb +208 -0
- data/lib/mirah/ast/structure.rb +226 -0
- data/lib/mirah/ast/type.rb +130 -0
- data/lib/mirah/compiler.rb +341 -0
- data/lib/mirah/env.rb +33 -0
- data/lib/mirah/jvm/base.rb +258 -0
- data/lib/mirah/jvm/compiler.rb +885 -0
- data/lib/mirah/jvm/method_lookup.rb +203 -0
- data/lib/mirah/jvm/source_compiler.rb +737 -0
- data/lib/mirah/jvm/source_generator/builder.rb +444 -0
- data/lib/mirah/jvm/source_generator/loops.rb +110 -0
- data/lib/mirah/jvm/source_generator/precompile.rb +188 -0
- data/lib/mirah/jvm/source_generator/typer.rb +11 -0
- data/lib/mirah/jvm/typer.rb +151 -0
- data/lib/mirah/jvm/types.rb +416 -0
- data/lib/mirah/jvm/types/basic_types.rb +33 -0
- data/lib/mirah/jvm/types/boolean.rb +17 -0
- data/lib/mirah/jvm/types/enumerable.rb +65 -0
- data/lib/mirah/jvm/types/extensions.rb +86 -0
- data/lib/mirah/jvm/types/factory.rb +186 -0
- data/lib/mirah/jvm/types/floats.rb +86 -0
- data/lib/mirah/jvm/types/integers.rb +171 -0
- data/lib/mirah/jvm/types/intrinsics.rb +376 -0
- data/lib/mirah/jvm/types/literals.rb +74 -0
- data/lib/mirah/jvm/types/methods.rb +614 -0
- data/lib/mirah/jvm/types/number.rb +143 -0
- data/lib/mirah/nbcompiler.rb +29 -0
- data/lib/mirah/plugin/edb.rb +29 -0
- data/lib/mirah/plugin/gwt.rb +173 -0
- data/lib/mirah/plugin/java.rb +55 -0
- data/lib/mirah/transform.rb +266 -0
- data/lib/mirah/transform2.rb +728 -0
- data/lib/mirah/typer.rb +407 -0
- data/lib/mirah_task.rb +107 -0
- data/test/test_ast.rb +359 -0
- data/test/test_compilation.rb +112 -0
- data/test/test_env.rb +42 -0
- data/test/test_gwt.rb +58 -0
- data/test/test_java_typer.rb +183 -0
- data/test/test_javac_compiler.rb +63 -0
- data/test/test_jvm_compiler.rb +2607 -0
- data/test/test_typer.rb +221 -0
- metadata +235 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
require 'mirah'
|
|
2
|
+
|
|
3
|
+
module Duby
|
|
4
|
+
module AST
|
|
5
|
+
class Fixnum
|
|
6
|
+
def compile(compiler, expression)
|
|
7
|
+
if expression
|
|
8
|
+
compiler.line(line_number)
|
|
9
|
+
compiler.fixnum(inferred_type, literal)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class Regexp
|
|
15
|
+
def compile(compiler, expression)
|
|
16
|
+
if expression
|
|
17
|
+
compiler.line(line_number)
|
|
18
|
+
compiler.regexp(literal)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class String
|
|
24
|
+
def compile(compiler, expression)
|
|
25
|
+
if expression
|
|
26
|
+
compiler.line(line_number)
|
|
27
|
+
compiler.string(literal)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class StringConcat
|
|
33
|
+
def compile(compiler, expression)
|
|
34
|
+
compiler.build_string(children, expression)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class ToString
|
|
39
|
+
def compile(compiler, expression)
|
|
40
|
+
compiler.to_string(body, expression)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class Float
|
|
45
|
+
def compile(compiler, expression)
|
|
46
|
+
if expression
|
|
47
|
+
compiler.line(line_number)
|
|
48
|
+
compiler.float(inferred_type, literal)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class Boolean
|
|
54
|
+
def compile(compiler, expression)
|
|
55
|
+
if expression
|
|
56
|
+
compiler.line(line_number)
|
|
57
|
+
compiler.boolean(literal)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
class Array
|
|
63
|
+
def compile(compiler, expression)
|
|
64
|
+
compiler.array(self, expression)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
class Body
|
|
69
|
+
def compile(compiler, expression)
|
|
70
|
+
compiler.line(line_number)
|
|
71
|
+
compiler.body(self, expression)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
class ScopedBody
|
|
76
|
+
def compile(compiler, expression)
|
|
77
|
+
compiler.line(line_number)
|
|
78
|
+
compiler.scoped_body(self, expression)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
class Import
|
|
83
|
+
def compile(compiler, expression)
|
|
84
|
+
# TODO: what does it mean for import to be an expression?
|
|
85
|
+
compiler.import(short, long)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
class Constant
|
|
90
|
+
def compile(compiler, expression)
|
|
91
|
+
if expression
|
|
92
|
+
compiler.line(line_number)
|
|
93
|
+
compiler.constant(self)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
class Print
|
|
99
|
+
def compile(compiler, expression)
|
|
100
|
+
# TODO: what does it mean for printline to be an expression?
|
|
101
|
+
compiler.line(line_number)
|
|
102
|
+
compiler.print(self)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
class Local
|
|
107
|
+
def compile(compiler, expression)
|
|
108
|
+
if expression
|
|
109
|
+
compiler.line(line_number)
|
|
110
|
+
if captured? && scope.has_binding?
|
|
111
|
+
compiler.captured_local(containing_scope, name, inferred_type)
|
|
112
|
+
else
|
|
113
|
+
compiler.local(containing_scope, name, inferred_type)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
class LocalDeclaration
|
|
120
|
+
def compile(compiler, expression)
|
|
121
|
+
compiler.line(line_number)
|
|
122
|
+
if captured? && scope.has_binding?
|
|
123
|
+
compiler.captured_local_declare(containing_scope, name, type)
|
|
124
|
+
else
|
|
125
|
+
compiler.local_declare(containing_scope, name, type)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
class LocalAssignment
|
|
131
|
+
def compile(compiler, expression)
|
|
132
|
+
compiler.line(line_number)
|
|
133
|
+
if captured? && scope.has_binding?
|
|
134
|
+
compiler.captured_local_assign(self, expression)
|
|
135
|
+
else
|
|
136
|
+
compiler.local_assign(containing_scope, name, inferred_type, expression, value)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
class Script
|
|
142
|
+
def compile(compiler, expression)
|
|
143
|
+
# TODO: what does it mean for a script to be an expression? possible?
|
|
144
|
+
compiler.define_main(self)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
class MethodDefinition
|
|
149
|
+
def compile(compiler, expression)
|
|
150
|
+
# TODO: what does it mean for a method to be an expression?
|
|
151
|
+
compiler.define_method(self)
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
class ConstructorDefinition
|
|
156
|
+
def compile(compiler, expression)
|
|
157
|
+
compiler.constructor(self)
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
class Arguments
|
|
162
|
+
def compile(compiler, expression)
|
|
163
|
+
# TODO: what does it mean for a method to be an expression?
|
|
164
|
+
args.each {|arg| compiler.declare_argument(arg.name, arg.inferred_type)} if args
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
class Noop
|
|
169
|
+
def compile(compiler, expression)
|
|
170
|
+
# TODO: what does it mean for a noop to be an expression
|
|
171
|
+
# nothing
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
class If
|
|
176
|
+
def compile(compiler, expression)
|
|
177
|
+
compiler.line(line_number)
|
|
178
|
+
compiler.branch(self, expression)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
class Condition
|
|
183
|
+
def compile(compiler, expression)
|
|
184
|
+
# TODO: can a condition ever be an expression? I don't think it can...
|
|
185
|
+
compiler.line(line_number)
|
|
186
|
+
predicate.compile(compiler, expression)
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
class FunctionalCall
|
|
191
|
+
def compile(compiler, expression)
|
|
192
|
+
compiler.line(line_number)
|
|
193
|
+
compiler.self_call(self, expression)
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
class Call
|
|
198
|
+
def compile(compiler, expression)
|
|
199
|
+
compiler.line(line_number)
|
|
200
|
+
compiler.call(self, expression)
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
class Super
|
|
205
|
+
def compile(compiler, expression)
|
|
206
|
+
compiler.line(line_number)
|
|
207
|
+
compiler.super_call(self, expression)
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
class Loop
|
|
212
|
+
def compile(compiler, expression)
|
|
213
|
+
compiler.line(line_number)
|
|
214
|
+
compiler.loop(self, expression)
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
class ClassDefinition
|
|
219
|
+
def compile(compiler, expression)
|
|
220
|
+
compiler.define_class(self, expression)
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
class ClosureDefinition
|
|
225
|
+
def compile(compiler, expression)
|
|
226
|
+
compiler.define_closure(self, expression)
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
class FieldDeclaration
|
|
231
|
+
def compile(compiler, expression)
|
|
232
|
+
compiler.field_declare(name, inferred_type, annotations, static)
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
class FieldAssignment
|
|
237
|
+
def compile(compiler, expression)
|
|
238
|
+
compiler.line(line_number)
|
|
239
|
+
compiler.field_assign(name, inferred_type, expression, value, annotations, static)
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
class Field
|
|
244
|
+
def compile(compiler, expression)
|
|
245
|
+
compiler.line(line_number)
|
|
246
|
+
if expression
|
|
247
|
+
compiler.field(name, inferred_type, annotations, static)
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
class AccessLevel
|
|
253
|
+
def compile(compiler, expression); end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
class Return
|
|
257
|
+
def compile(compiler, expression)
|
|
258
|
+
compiler.line(line_number)
|
|
259
|
+
compiler.return(self)
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
class EmptyArray
|
|
264
|
+
def compile(compiler, expression)
|
|
265
|
+
if expression
|
|
266
|
+
compiler.line(line_number)
|
|
267
|
+
compiler.empty_array(component_type, size)
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
class Null
|
|
273
|
+
def compile(compiler, expression)
|
|
274
|
+
if expression
|
|
275
|
+
compiler.line(line_number)
|
|
276
|
+
compiler.null
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
class Break
|
|
282
|
+
def compile(compiler, expression)
|
|
283
|
+
compiler.line(line_number)
|
|
284
|
+
compiler.break(self)
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
class Next
|
|
289
|
+
def compile(compiler, expression)
|
|
290
|
+
compiler.line(line_number)
|
|
291
|
+
compiler.next(self)
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
class Redo
|
|
296
|
+
def compile(compiler, expression)
|
|
297
|
+
compiler.line(line_number)
|
|
298
|
+
compiler.redo(self)
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
class Raise
|
|
303
|
+
def compile(compiler, expression)
|
|
304
|
+
compiler.line(line_number)
|
|
305
|
+
compiler._raise(exception)
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
class Rescue
|
|
310
|
+
def compile(compiler, expression)
|
|
311
|
+
compiler.line(line_number)
|
|
312
|
+
compiler.rescue(self, expression)
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
class Ensure
|
|
317
|
+
def compile(compiler, expression)
|
|
318
|
+
compiler.line(line_number)
|
|
319
|
+
compiler.ensure(self, expression)
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
class Self
|
|
324
|
+
def compile(compiler, expression)
|
|
325
|
+
if expression
|
|
326
|
+
compiler.line(line_number)
|
|
327
|
+
compiler.compile_self
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
class BindingReference
|
|
333
|
+
def compile(compiler, expression)
|
|
334
|
+
if expression
|
|
335
|
+
compiler.line(line_number)
|
|
336
|
+
compiler.binding_reference
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
end
|
data/lib/mirah/env.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'rbconfig'
|
|
2
|
+
|
|
3
|
+
module Duby
|
|
4
|
+
module Env
|
|
5
|
+
|
|
6
|
+
# Returns the system PATH_SEPARATOR environment variable value. This is used when
|
|
7
|
+
# separating multiple paths in one string. If none is defined then a : (colon)
|
|
8
|
+
# is returned
|
|
9
|
+
def self.path_seperator
|
|
10
|
+
ps = RbConfig::CONFIG['PATH_SEPARATOR']
|
|
11
|
+
ps = ':' if ps.nil? || ps == ''
|
|
12
|
+
ps
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Takes an array of strings and joins them using the path_separator returning
|
|
16
|
+
# a single string value
|
|
17
|
+
def self.encode_paths(paths)
|
|
18
|
+
paths.join(path_seperator)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Takes a single string value "paths" and returns an array of strings containing the
|
|
22
|
+
# original string separated using the path_separator. An option second parameter
|
|
23
|
+
# is an array that will have the strings appended to it. If the optional array parameter
|
|
24
|
+
# is supplied it is returned as the result
|
|
25
|
+
def self.decode_paths(paths, dest = nil)
|
|
26
|
+
result = dest ? dest : []
|
|
27
|
+
paths.split(path_seperator).each do |path|
|
|
28
|
+
result << path
|
|
29
|
+
end
|
|
30
|
+
result
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
module Duby
|
|
2
|
+
module Compiler
|
|
3
|
+
class JVMCompilerBase
|
|
4
|
+
attr_accessor :filename, :method, :static, :class
|
|
5
|
+
|
|
6
|
+
class CompilationError < Exception
|
|
7
|
+
attr_accessor :node
|
|
8
|
+
def initialize(msg, node = nil)
|
|
9
|
+
super(msg)
|
|
10
|
+
@node = node
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@jump_scope = []
|
|
16
|
+
@bindings = Hash.new {|h, type| h[type] = type.define(@file)}
|
|
17
|
+
@captured_locals = Hash.new {|h, binding| h[binding] = {}}
|
|
18
|
+
@self_scope = nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def error(message, node)
|
|
22
|
+
raise CompilationError.new(message, node)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def compile(ast, expression = false)
|
|
26
|
+
begin
|
|
27
|
+
ast.compile(self, expression)
|
|
28
|
+
rescue => ex
|
|
29
|
+
Duby.print_error(ex.message, ast.position)
|
|
30
|
+
raise ex
|
|
31
|
+
end
|
|
32
|
+
log "Compilation successful!"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def log(message); JVM.log(message); end
|
|
36
|
+
|
|
37
|
+
def toplevel_class
|
|
38
|
+
@class = @type.define(@file)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def generate
|
|
42
|
+
log "Generating #{output_type}..."
|
|
43
|
+
@file.generate do |filename, builder|
|
|
44
|
+
log " #{builder.class_name}"
|
|
45
|
+
if block_given?
|
|
46
|
+
yield filename, builder
|
|
47
|
+
else
|
|
48
|
+
File.open(filename, 'wb') {|f| f.write(builder.generate)}
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
log "...done!"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def define_main(script)
|
|
55
|
+
@static = true
|
|
56
|
+
@filename = File.basename(script.filename)
|
|
57
|
+
classname = JVM.classname_from_filename(@filename)
|
|
58
|
+
@type = AST.type(script, classname)
|
|
59
|
+
@file = file_builder(@filename)
|
|
60
|
+
body = script.body
|
|
61
|
+
body = body[0] if body.children.size == 1
|
|
62
|
+
if body.class != AST::ClassDefinition
|
|
63
|
+
@class = @type.define(@file)
|
|
64
|
+
with :method => @class.main do
|
|
65
|
+
log "Starting main method"
|
|
66
|
+
|
|
67
|
+
@method.start
|
|
68
|
+
@current_scope = script.static_scope
|
|
69
|
+
declare_locals(@current_scope)
|
|
70
|
+
begin_main
|
|
71
|
+
|
|
72
|
+
prepare_binding(script) do
|
|
73
|
+
body.compile(self, false)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
finish_main
|
|
77
|
+
@method.stop
|
|
78
|
+
end
|
|
79
|
+
@class.stop
|
|
80
|
+
else
|
|
81
|
+
body.compile(self, false)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
log "Main method complete!"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def begin_main; end
|
|
88
|
+
def finish_main; end
|
|
89
|
+
|
|
90
|
+
# arg_types must be an Array
|
|
91
|
+
def create_method_builder(name, node, static, exceptions, return_type, arg_types)
|
|
92
|
+
@class.build_method(name.to_s, node.visibility, static,
|
|
93
|
+
exceptions, return_type, *arg_types)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def base_define_method(node, args_are_types)
|
|
97
|
+
name, signature, args = node.name, node.signature, node.arguments.args
|
|
98
|
+
if name == "initialize" && node.static?
|
|
99
|
+
name = "<clinit>"
|
|
100
|
+
end
|
|
101
|
+
if args_are_types
|
|
102
|
+
arg_types = args.map { |arg| arg.inferred_type } if args
|
|
103
|
+
else
|
|
104
|
+
arg_types = args
|
|
105
|
+
end
|
|
106
|
+
arg_types ||= []
|
|
107
|
+
return_type = signature[:return]
|
|
108
|
+
exceptions = signature[:throws]
|
|
109
|
+
|
|
110
|
+
with :static => @static || node.static?, :current_scope => node.static_scope do
|
|
111
|
+
method = create_method_builder(name, node, @static, exceptions,
|
|
112
|
+
return_type, arg_types)
|
|
113
|
+
annotate(method, node.annotations)
|
|
114
|
+
yield method, arg_types
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
arg_types_for_opt = []
|
|
118
|
+
args_for_opt = []
|
|
119
|
+
if args
|
|
120
|
+
args.each do |arg|
|
|
121
|
+
if AST::OptionalArgument === arg
|
|
122
|
+
new_args = if args_are_types
|
|
123
|
+
arg_types_for_opt
|
|
124
|
+
else
|
|
125
|
+
args_for_opt
|
|
126
|
+
end
|
|
127
|
+
method = create_method_builder(name, node, @static, exceptions,
|
|
128
|
+
return_type, new_args)
|
|
129
|
+
with :method => method do
|
|
130
|
+
log "Starting new method #{name}(#{arg_types_for_opt})"
|
|
131
|
+
|
|
132
|
+
annotate(method, node.annotations)
|
|
133
|
+
@method.start
|
|
134
|
+
|
|
135
|
+
define_optarg_chain(name, arg,
|
|
136
|
+
return_type,
|
|
137
|
+
args_for_opt,
|
|
138
|
+
arg_types_for_opt)
|
|
139
|
+
|
|
140
|
+
@method.stop
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
arg_types_for_opt << arg.inferred_type
|
|
144
|
+
args_for_opt << arg
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def constructor(node, args_are_types)
|
|
150
|
+
args = node.arguments.args || []
|
|
151
|
+
arg_types = if args_are_types
|
|
152
|
+
args.map { |arg| arg.inferred_type }
|
|
153
|
+
else
|
|
154
|
+
args
|
|
155
|
+
end
|
|
156
|
+
exceptions = node.signature[:throws]
|
|
157
|
+
method = @class.build_constructor(node.visibility, exceptions, *arg_types)
|
|
158
|
+
annotate(method, node.annotations)
|
|
159
|
+
with :current_scope => node.static_scope do
|
|
160
|
+
yield(method, args)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def define_class(class_def, expression)
|
|
165
|
+
with(:type => class_def.inferred_type,
|
|
166
|
+
:class => class_def.inferred_type.define(@file),
|
|
167
|
+
:static => false) do
|
|
168
|
+
annotate(@class, class_def.annotations)
|
|
169
|
+
class_def.body.compile(self, false) if class_def.body
|
|
170
|
+
@class.stop
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def declare_argument(name, type)
|
|
175
|
+
# declare local vars for arguments here
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def body(body, expression)
|
|
179
|
+
saved_self = @self_scope
|
|
180
|
+
if body.kind_of?(Duby::AST::ScopedBody)
|
|
181
|
+
scope = body.static_scope
|
|
182
|
+
declare_locals(scope)
|
|
183
|
+
if scope != @self_scope
|
|
184
|
+
@self_scope = scope
|
|
185
|
+
if scope.self_node
|
|
186
|
+
# FIXME This is a horrible hack!
|
|
187
|
+
# Instead we should eliminate unused self's.
|
|
188
|
+
unless scope.self_type.name == 'mirah.impl.Builtin'
|
|
189
|
+
local_assign(
|
|
190
|
+
scope, 'self', scope.self_type, false, scope.self_node)
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
# all except the last element in a body of code is treated as a statement
|
|
196
|
+
i, last = 0, body.children.size - 1
|
|
197
|
+
while i < last
|
|
198
|
+
body.children[i].compile(self, false)
|
|
199
|
+
i += 1
|
|
200
|
+
end
|
|
201
|
+
yield body.children[last] if last >= 0
|
|
202
|
+
@self_scope = saved_self
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def scoped_body(scope, expression)
|
|
206
|
+
body(scope, expression)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def scoped_local_name(name, scope=nil)
|
|
210
|
+
if scope.nil? || scope == @current_scope
|
|
211
|
+
name
|
|
212
|
+
else
|
|
213
|
+
"#{name}$#{scope.object_id}"
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def import(short, long)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def fixnum(type, value)
|
|
221
|
+
type.literal(method, value)
|
|
222
|
+
end
|
|
223
|
+
alias float fixnum
|
|
224
|
+
|
|
225
|
+
def compile_self
|
|
226
|
+
if @self_scope && @self_scope.self_node
|
|
227
|
+
local(@self_scope, 'self', @self_scope.self_type)
|
|
228
|
+
else
|
|
229
|
+
real_self
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def get_binding(type)
|
|
234
|
+
@bindings[type]
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def declared_captures(binding=nil)
|
|
238
|
+
@captured_locals[binding || @binding]
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def with(vars)
|
|
242
|
+
orig_values = {}
|
|
243
|
+
begin
|
|
244
|
+
vars.each do |name, new_value|
|
|
245
|
+
name = "@#{name}"
|
|
246
|
+
orig_values[name] = instance_variable_get name
|
|
247
|
+
instance_variable_set name, new_value
|
|
248
|
+
end
|
|
249
|
+
yield
|
|
250
|
+
ensure
|
|
251
|
+
orig_values.each do |name, value|
|
|
252
|
+
instance_variable_set name, value
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|