duby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/History.txt +4 -0
  2. data/Manifest.txt +68 -0
  3. data/README.txt +31 -0
  4. data/Rakefile +37 -0
  5. data/bin/duby +9 -0
  6. data/bin/dubyc +9 -0
  7. data/bin/dubyp +9 -0
  8. data/examples/appengine/src/com/google/appengine/ext/duby/db/Model.duby +132 -0
  9. data/examples/appengine/src/com/ribrdb/DubyApp.duby +28 -0
  10. data/examples/bench_fractal.duby +57 -0
  11. data/examples/construction.duby +8 -0
  12. data/examples/edb.duby +3 -0
  13. data/examples/fib.duby +24 -0
  14. data/examples/fields.duby +22 -0
  15. data/examples/java_thing.duby +13 -0
  16. data/examples/simple_class.duby +12 -0
  17. data/examples/swing.duby +20 -0
  18. data/examples/tak.duby +15 -0
  19. data/javalib/JRubyParser.jar +0 -0
  20. data/lib/duby.rb +170 -0
  21. data/lib/duby/ast.rb +340 -0
  22. data/lib/duby/ast/call.rb +73 -0
  23. data/lib/duby/ast/class.rb +145 -0
  24. data/lib/duby/ast/flow.rb +328 -0
  25. data/lib/duby/ast/intrinsics.rb +46 -0
  26. data/lib/duby/ast/literal.rb +93 -0
  27. data/lib/duby/ast/local.rb +77 -0
  28. data/lib/duby/ast/method.rb +187 -0
  29. data/lib/duby/ast/structure.rb +44 -0
  30. data/lib/duby/ast/type.rb +93 -0
  31. data/lib/duby/c/compiler.rb +134 -0
  32. data/lib/duby/compiler.rb +261 -0
  33. data/lib/duby/jvm/compiler.rb +684 -0
  34. data/lib/duby/jvm/method_lookup.rb +185 -0
  35. data/lib/duby/jvm/source_compiler.rb +516 -0
  36. data/lib/duby/jvm/source_generator/builder.rb +368 -0
  37. data/lib/duby/jvm/source_generator/loops.rb +132 -0
  38. data/lib/duby/jvm/source_generator/precompile.rb +154 -0
  39. data/lib/duby/jvm/source_generator/typer.rb +11 -0
  40. data/lib/duby/jvm/typer.rb +118 -0
  41. data/lib/duby/jvm/types.rb +326 -0
  42. data/lib/duby/jvm/types/basic_types.rb +18 -0
  43. data/lib/duby/jvm/types/boolean.rb +11 -0
  44. data/lib/duby/jvm/types/factory.rb +151 -0
  45. data/lib/duby/jvm/types/floats.rb +70 -0
  46. data/lib/duby/jvm/types/integers.rb +110 -0
  47. data/lib/duby/jvm/types/intrinsics.rb +157 -0
  48. data/lib/duby/jvm/types/literals.rb +82 -0
  49. data/lib/duby/jvm/types/methods.rb +344 -0
  50. data/lib/duby/jvm/types/number.rb +92 -0
  51. data/lib/duby/nbcompiler.rb +29 -0
  52. data/lib/duby/old/compiler_old.rb +845 -0
  53. data/lib/duby/old/declaration.rb +72 -0
  54. data/lib/duby/old/mapper.rb +72 -0
  55. data/lib/duby/old/signature.rb +52 -0
  56. data/lib/duby/old/typer_old.rb +163 -0
  57. data/lib/duby/plugin/edb.rb +25 -0
  58. data/lib/duby/plugin/java.rb +42 -0
  59. data/lib/duby/plugin/math.rb +84 -0
  60. data/lib/duby/transform.rb +908 -0
  61. data/lib/duby/typer.rb +359 -0
  62. data/test/test_ast.rb +391 -0
  63. data/test/test_compilation.rb +98 -0
  64. data/test/test_java_typer.rb +199 -0
  65. data/test/test_javac_compiler.rb +57 -0
  66. data/test/test_jvm_compiler.rb +1459 -0
  67. data/test/test_math_plugin.rb +87 -0
  68. data/test/test_typer.rb +246 -0
  69. metadata +155 -0
@@ -0,0 +1,684 @@
1
+ require 'duby'
2
+ require 'duby/jvm/method_lookup'
3
+ require 'duby/jvm/types'
4
+ require 'duby/typer'
5
+ require 'duby/plugin/java'
6
+ require 'bitescript'
7
+
8
+ module Duby
9
+ module AST
10
+ class FunctionalCall
11
+ attr_accessor :target
12
+ end
13
+ end
14
+
15
+ module Compiler
16
+ class JVM
17
+ java_import java.lang.System
18
+ java_import java.io.PrintStream
19
+ include Duby::JVM::MethodLookup
20
+ Types = Duby::JVM::Types
21
+
22
+ class << self
23
+ attr_accessor :verbose
24
+
25
+ def log(message)
26
+ puts "* [#{name}] #{message}" if JVM.verbose
27
+ end
28
+ end
29
+
30
+ module JVMLogger
31
+ def log(message); JVM.log(message); end
32
+ end
33
+ include JVMLogger
34
+
35
+ class ImplicitSelf
36
+ attr_reader :inferred_type
37
+
38
+ def initialize(type)
39
+ @inferred_type = type
40
+ end
41
+
42
+ def compile(compiler, expression)
43
+ if expression
44
+ compiler.method.aload(0)
45
+ end
46
+ end
47
+ end
48
+
49
+ attr_accessor :filename, :src, :method, :static, :class
50
+
51
+ def initialize(filename)
52
+ @filename = File.basename(filename)
53
+ @src = ""
54
+ @static = true
55
+ classname = File.basename(filename, '.duby')
56
+
57
+ @file = BiteScript::FileBuilder.new(@filename)
58
+ AST.type_factory.define_types(@file)
59
+ @type = AST::type(classname)
60
+ @class = @type.define(@file)
61
+ end
62
+
63
+ def compile(ast, expression = false)
64
+ ast.compile(self, expression)
65
+ log "Compilation successful!"
66
+ end
67
+
68
+ def define_main(body)
69
+ with :method => @class.main do
70
+ log "Starting main method"
71
+
72
+ @method.start
73
+
74
+ # declare argv variable
75
+ @method.local('argv', AST.type('string', true))
76
+
77
+ body.compile(self, false)
78
+
79
+ @method.returnvoid
80
+ @method.stop
81
+ end
82
+
83
+ log "Main method complete!"
84
+ end
85
+
86
+ def define_method(name, signature, args, body, force_static)
87
+ arg_types = if args.args
88
+ args.args.map { |arg| arg.inferred_type }
89
+ else
90
+ []
91
+ end
92
+ return_type = signature[:return]
93
+ exceptions = signature[:throws]
94
+ started = false
95
+ if @static || force_static
96
+ method = @class.public_static_method(name.to_s, exceptions, return_type, *arg_types)
97
+ else
98
+ if name == "initialize"
99
+ method = @class.public_constructor(exceptions, *arg_types)
100
+ method.start
101
+ method.aload 0
102
+ method.invokespecial @class.superclass, "<init>", [@method.void]
103
+ started = true
104
+ else
105
+ method = @class.public_method(name.to_s, exceptions, return_type, *arg_types)
106
+ end
107
+ end
108
+
109
+ return if @class.interface?
110
+
111
+ with :method => method, :static => @static || force_static do
112
+ log "Starting new method #{name}(#{arg_types})"
113
+
114
+ @method.start unless started
115
+
116
+ # declare all args so they get their values
117
+ if args.args
118
+ args.args.each {|arg| @method.local(arg.name, arg.inferred_type)}
119
+ end
120
+
121
+ expression = signature[:return] != Types::Void
122
+ body.compile(self, expression) if body
123
+
124
+ if name == "initialize"
125
+ @method.returnvoid
126
+ else
127
+ signature[:return].return(@method)
128
+ end
129
+
130
+ @method.stop
131
+ end
132
+
133
+ arg_types_for_opt = []
134
+ args_for_opt = []
135
+ if args.args
136
+ args.args.each do |arg|
137
+ if AST::OptionalArgument === arg
138
+ if @static || force_static
139
+ method = @class.public_static_method(name.to_s, exceptions, return_type, *arg_types_for_opt)
140
+ else
141
+ if name == "initialize"
142
+ method = @class.public_constructor(exceptions, *arg_types_for_opt)
143
+ method.start
144
+ method.aload 0
145
+ method.invokespecial @class.superclass, "<init>", [@method.void]
146
+ started = true
147
+ else
148
+ method = @class.public_method(name.to_s, exceptions, return_type, *arg_types_for_opt)
149
+ end
150
+ end
151
+
152
+ with :method => method, :static => @static || force_static do
153
+ log "Starting new method #{name}(#{arg_types_for_opt})"
154
+
155
+ @method.start unless started
156
+
157
+ # declare all args so they get their values
158
+
159
+ expression = signature[:return] != Types::Void
160
+
161
+ @method.aload(0) unless @static
162
+ args_for_opt.each {|req_arg| @method.local(req_arg.name, req_arg.inferred_type)}
163
+ arg.children[0].compile(self, true)
164
+
165
+ # invoke the next one in the chain
166
+ if @static
167
+ @method.invokestatic(@class, name.to_s, [return_type] + arg_types_for_opt + [arg.inferred_type])
168
+ else
169
+ @method.invokevirtual(@class, name.to_s, [return_type] + arg_types_for_opt + [arg.inferred_type])
170
+ end
171
+
172
+ if name == "initialize"
173
+ @method.returnvoid
174
+ else
175
+ signature[:return].return(@method)
176
+ end
177
+
178
+ @method.stop
179
+ end
180
+ end
181
+ arg_types_for_opt << arg.inferred_type
182
+ args_for_opt << arg
183
+ end
184
+ end
185
+
186
+ log "Method #{name}(#{arg_types}) complete!"
187
+ end
188
+
189
+ def define_class(class_def, expression)
190
+ with(:type => class_def.inferred_type,
191
+ :class => class_def.inferred_type.define(@file),
192
+ :static => false) do
193
+ class_def.body.compile(self, false) if class_def.body
194
+
195
+ @class.stop
196
+ end
197
+ end
198
+
199
+ def declare_argument(name, type)
200
+ # declare local vars for arguments here
201
+ end
202
+
203
+ def branch(iff, expression)
204
+ elselabel = @method.label
205
+ donelabel = @method.label
206
+
207
+ # this is ugly...need a better way to abstract the idea of compiling a
208
+ # conditional branch while still fitting into JVM opcodes
209
+ predicate = iff.condition.predicate
210
+ if iff.body || expression
211
+ jump_if_not(predicate, elselabel)
212
+
213
+ if iff.body
214
+ iff.body.compile(self, expression)
215
+ elsif expression
216
+ iff.inferred_type.init_value(@method)
217
+ end
218
+
219
+ @method.goto(donelabel)
220
+ else
221
+ jump_if(predicate, donelabel)
222
+ end
223
+
224
+ elselabel.set!
225
+
226
+ if iff.else
227
+ iff.else.compile(self, expression)
228
+ elsif expression
229
+ iff.inferred_type.init_value(@method)
230
+ end
231
+
232
+ donelabel.set!
233
+ end
234
+
235
+ def while_loop(loop, expression)
236
+ with(:break_label => @method.label,
237
+ :redo_label => @method.label,
238
+ :next_label => @method.label) do
239
+ # TODO: not checking "check first" or "negative"
240
+ predicate = loop.condition.predicate
241
+
242
+ if loop.check_first
243
+ @next_label.set!
244
+ if loop.negative
245
+ # if condition, exit
246
+ jump_if(predicate, @break_label)
247
+ else
248
+ # if not condition, exit
249
+ jump_if_not(predicate, @break_label)
250
+ end
251
+ end
252
+
253
+ @redo_label.set!
254
+ loop.body.compile(self, false)
255
+
256
+ unless loop.check_first
257
+ @next_label.set!
258
+ if loop.negative
259
+ # if not condition, continue
260
+ jump_if_not(predicate, @redo_label)
261
+ else
262
+ # if condition, continue
263
+ jump_if(predicate, @redo_label)
264
+ end
265
+ else
266
+ @method.goto(@next_label)
267
+ end
268
+
269
+ @break_label.set!
270
+
271
+ # loops always evaluate to null
272
+ @method.aconst_null if expression
273
+ end
274
+ end
275
+
276
+ def for_loop(loop, expression)
277
+ if loop.iter.inferred_type.array?
278
+ array_foreach(loop, expression)
279
+ else
280
+ iterator_foreach(loop, expression)
281
+ end
282
+ end
283
+
284
+ def array_foreach(loop, expression)
285
+ array = "tmp$#{loop.name}$array"
286
+ i = "tmp$#{loop.name}$i"
287
+ length = "tmp$#{loop.name}$length"
288
+ array_type = loop.iter.inferred_type
289
+ item_type = array_type.component_type
290
+ local_assign(array, array_type, true, loop.iter)
291
+ @method.arraylength
292
+ @method.istore(@method.local(length, Types::Int))
293
+ @method.push_int(0)
294
+ @method.istore(@method.local(i, Types::Int))
295
+ with(:break_label => @method.label,
296
+ :redo_label => @method.label,
297
+ :next_label => @method.label) do
298
+ @next_label.set!
299
+ local(i, Types::Int)
300
+ local(length, Types::Int)
301
+ @method.if_icmpge(@break_label)
302
+ local(array, array_type)
303
+ local(i, Types::Int)
304
+ item_type.aload(@method)
305
+ item_type.store(@method, @method.local(loop.name, item_type))
306
+ @method.iinc(@method.local(i, Types::Int), 1)
307
+
308
+ @redo_label.set!
309
+ loop.body.compile(self, false)
310
+ @method.goto @next_label
311
+
312
+ @break_label.set!
313
+
314
+ # loops always evaluate to null
315
+ @method.aconst_null if expression
316
+ end
317
+ end
318
+
319
+ def break(node)
320
+ handle_ensures(node)
321
+ @method.goto(@break_label)
322
+ end
323
+
324
+ def next(node)
325
+ handle_ensures(node)
326
+ @method.goto(@next_label)
327
+ end
328
+
329
+ def redo(node)
330
+ handle_ensures(node)
331
+ @method.goto(@redo_label)
332
+ end
333
+
334
+ def jump_if(predicate, target)
335
+ raise "Expected boolean, found #{predicate.inferred_type}" unless predicate.inferred_type == Types::Boolean
336
+ predicate.compile(self, true)
337
+ @method.ifne(target)
338
+ end
339
+
340
+ def jump_if_not(predicate, target)
341
+ raise "Expected boolean, found #{predicate.inferred_type}" unless predicate.inferred_type == Types::Boolean
342
+ predicate.compile(self, true)
343
+ @method.ifeq(target)
344
+ end
345
+
346
+ def call(call, expression)
347
+
348
+ target = call.target.inferred_type
349
+ params = call.parameters.map do |param|
350
+ param.inferred_type
351
+ end
352
+ method = target.get_method(call.name, params)
353
+ if method
354
+ method.call(self, call, expression)
355
+ else
356
+ raise "Missing method #{target}.#{call.name}(#{params.join ', '})"
357
+ end
358
+ end
359
+
360
+ def self_call(fcall, expression)
361
+ return cast(fcall, expression) if fcall.cast?
362
+ type = @type
363
+ type = type.meta if @static
364
+ fcall.target = ImplicitSelf.new(type)
365
+
366
+ params = fcall.parameters.map do |param|
367
+ param.inferred_type
368
+ end
369
+ method = type.get_method(fcall.name, params)
370
+ unless method
371
+ target = static ? @class.name : 'self'
372
+
373
+ raise NameError, "No method %s.%s(%s)" %
374
+ [target, fcall.name, params.join(', ')]
375
+ end
376
+ method.call(self, fcall, expression)
377
+ end
378
+
379
+ def cast(fcall, expression)
380
+ # casting operation, not a call
381
+ castee = fcall.parameters[0]
382
+
383
+ # TODO move errors to inference phase
384
+ source_type_name = castee.inferred_type.name
385
+ target_type_name = fcall.inferred_type.name
386
+ case source_type_name
387
+ when "byte", "short", "char", "int", "long", "float", "double"
388
+ case target_type_name
389
+ when "byte", "short", "char", "int", "long", "float", "double"
390
+ # ok
391
+ primitive = true
392
+ else
393
+ raise TypeError.new "not a reference type: #{castee.inferred_type}"
394
+ end
395
+ when "boolean"
396
+ if target_type_name != "boolean"
397
+ raise TypeError.new "not a boolean type: #{castee.inferred_type}"
398
+ end
399
+ primitive = true
400
+ else
401
+ case target_type_name
402
+ when "byte", "short", "char", "int", "long", "float", "double"
403
+ raise TypeError.new "not a primitive type: #{castee.inferred_type}"
404
+ else
405
+ # ok
406
+ primitive = false
407
+ end
408
+ end
409
+
410
+ castee.compile(self, expression)
411
+ if expression
412
+ if primitive
413
+ source_type_name = 'int' if %w[byte short char].include? source_type_name
414
+ if (source_type_name != 'int') && (%w[byte short char].include? target_type_name)
415
+ target_type_name = 'int'
416
+ end
417
+
418
+ if source_type_name != target_type_name
419
+ if RUBY_VERSION == "1.9"
420
+ @method.send "#{source_type_name[0]}2#{target_type_name[0]}"
421
+ else
422
+ @method.send "#{source_type_name[0].chr}2#{target_type_name[0].chr}"
423
+ end
424
+ end
425
+ else
426
+ if source_type_name != target_type_name
427
+ @method.checkcast fcall.inferred_type
428
+ end
429
+ end
430
+ end
431
+ end
432
+
433
+ def body(body, expression)
434
+ # all except the last element in a body of code is treated as a statement
435
+ i, last = 0, body.children.size - 1
436
+ while i < last
437
+ body.children[i].compile(self, false)
438
+ i += 1
439
+ end
440
+ # last element is an expression only if the body is an expression
441
+ body.children[last].compile(self, expression)
442
+ end
443
+
444
+ def local(name, type)
445
+ type.load(@method, @method.local(name, type))
446
+ end
447
+
448
+ def local_assign(name, type, expression, value)
449
+ declare_local(name, type)
450
+
451
+ value.compile(self, true)
452
+
453
+ # if expression, dup the value we're assigning
454
+ @method.dup if expression
455
+
456
+ type.store(@method, @method.local(name, type))
457
+ end
458
+
459
+ def declared_locals
460
+ @declared_locals ||= {}
461
+ end
462
+
463
+ def declare_local(name, type)
464
+ # TODO confirm types are compatible
465
+ unless declared_locals[name]
466
+ declared_locals[name] = type
467
+ index = @method.local(name, type)
468
+ end
469
+ end
470
+
471
+ def local_declare(name, type)
472
+ declare_local(name, type)
473
+ type.init_value(@method)
474
+ type.store(@method, @method.local(name, type))
475
+ end
476
+
477
+ def field(name, type)
478
+ name = name[1..-1]
479
+
480
+ # load self object unless static
481
+ method.aload 0 unless static
482
+
483
+ if static
484
+ @method.getstatic(@class, name, type)
485
+ else
486
+ @method.getfield(@class, name, type)
487
+ end
488
+ end
489
+
490
+ def declared_fields
491
+ @declared_fields ||= {}
492
+ end
493
+
494
+ def declare_field(name, type)
495
+ # TODO confirm types are compatible
496
+ unless declared_fields[name]
497
+ declared_fields[name] = type
498
+ if static
499
+ @class.private_static_field name, type
500
+ else
501
+ @class.private_field name, type
502
+ end
503
+ end
504
+ end
505
+
506
+ def field_declare(name, type)
507
+ name = name[1..-1]
508
+ declare_field(name, type)
509
+ end
510
+
511
+ def field_assign(name, type, expression, value)
512
+ name = name[1..-1]
513
+
514
+ real_type = declared_fields[name] || type
515
+
516
+ declare_field(name, real_type)
517
+
518
+ method.aload 0 unless static
519
+ value.compile(self, true)
520
+ if expression
521
+ instruction = 'dup'
522
+ instruction << '2' if type.wide?
523
+ instruction << '_x1' unless static
524
+ method.send instruction
525
+ end
526
+
527
+ if static
528
+ @method.putstatic(@class, name, real_type)
529
+ else
530
+ @method.putfield(@class, name, real_type)
531
+ end
532
+ end
533
+
534
+ def string(value)
535
+ @method.ldc(value)
536
+ end
537
+
538
+ def boolean(value)
539
+ value ? @method.iconst_1 : @method.iconst_0
540
+ end
541
+
542
+ def null
543
+ @method.aconst_null
544
+ end
545
+
546
+ def newline
547
+ # TODO: line numbering
548
+ end
549
+
550
+ def line(num)
551
+ @method.line(num) if @method
552
+ end
553
+
554
+ def generate
555
+ @class.stop
556
+ log "Generating classes..."
557
+ @file.generate do |filename, builder|
558
+ log " #{builder.class_name}"
559
+ if block_given?
560
+ yield filename, builder
561
+ else
562
+ File.open(filename, 'w') {|f| f.write(builder.generate)}
563
+ end
564
+ end
565
+ log "...done!"
566
+ end
567
+
568
+ def import(short, long)
569
+ end
570
+
571
+ def print(print_node)
572
+ @method.getstatic System, "out", PrintStream
573
+ print_node.parameters.each {|param| param.compile(self, true)}
574
+ params = print_node.parameters.map {|param| param.inferred_type.jvm_type}
575
+ method_name = print_node.println ? "println" : "print"
576
+ method = find_method(PrintStream.java_class, method_name, params, false)
577
+ if (method)
578
+ @method.invokevirtual(
579
+ PrintStream,
580
+ method_name,
581
+ [method.return_type, *method.parameter_types])
582
+ else
583
+ log "Could not find a match for #{PrintStream}.#{method_name}(#{params})"
584
+ fail "Could not compile"
585
+ end
586
+ end
587
+
588
+ def return(return_node)
589
+ return_node.value.compile(self, true)
590
+ handle_ensures(return_node)
591
+ return_node.inferred_type.return(@method)
592
+ end
593
+
594
+ def _raise(exception)
595
+ exception.compile(self, true)
596
+ @method.athrow
597
+ end
598
+
599
+ def rescue(rescue_node, expression)
600
+ start = @method.label.set!
601
+ body_end = @method.label
602
+ done = @method.label
603
+ rescue_node.body.compile(self, expression)
604
+ body_end.set!
605
+ @method.goto(done)
606
+ rescue_node.clauses.each do |clause|
607
+ target = @method.label.set!
608
+ if clause.name
609
+ @method.astore(@method.push_local(clause.name, clause.type))
610
+ else
611
+ @method.pop
612
+ end
613
+ clause.body.compile(self, expression)
614
+ @method.pop_local(clause.name) if clause.name
615
+ @method.goto(done)
616
+ clause.types.each do |type|
617
+ @method.trycatch(start, body_end, target, type)
618
+ end
619
+ end
620
+ done.set!
621
+ end
622
+
623
+ def handle_ensures(node)
624
+ return unless node.ensures
625
+ node.ensures.each do |ensure_node|
626
+ ensure_node.clause.compile(self, false)
627
+ end
628
+ end
629
+
630
+ def ensure(node, expression)
631
+ node.state = @method.label # Save the ensure target for JumpNodes
632
+ start = @method.label.set!
633
+ body_end = @method.label
634
+ done = @method.label
635
+ node.body.compile(self, expression) # First compile the body
636
+ body_end.set!
637
+ handle_ensures(node) # run the ensure clause
638
+ @method.goto(done) # and continue on after the exception handler
639
+ target = @method.label.set! # Finally, create the exception handler
640
+ @method.trycatch(start, body_end, target, nil)
641
+ handle_ensures(node)
642
+ @method.athrow
643
+ done.set!
644
+ end
645
+
646
+ def empty_array(type, size)
647
+ size.compile(self, true)
648
+ type.newarray(@method)
649
+ end
650
+
651
+ def with(vars)
652
+ orig_values = {}
653
+ begin
654
+ vars.each do |name, new_value|
655
+ name = "@#{name}"
656
+ orig_values[name] = instance_variable_get name
657
+ instance_variable_set name, new_value
658
+ end
659
+ yield
660
+ ensure
661
+ orig_values.each do |name, value|
662
+ instance_variable_set name, value
663
+ end
664
+ end
665
+ end
666
+ end
667
+ end
668
+ end
669
+
670
+ if __FILE__ == $0
671
+ Duby::Typer.verbose = true
672
+ Duby::AST.verbose = true
673
+ Duby::Compiler::JVM.verbose = true
674
+ ast = Duby::AST.parse(File.read(ARGV[0]))
675
+
676
+ typer = Duby::Typer::Simple.new(:script)
677
+ ast.infer(typer)
678
+ typer.resolve(true)
679
+
680
+ compiler = Duby::Compiler::JVM.new(ARGV[0])
681
+ compiler.compile(ast)
682
+
683
+ compiler.generate
684
+ end