duby 0.0.1

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.
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