duby 0.0.2-java → 0.0.3-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.
Files changed (72) hide show
  1. data/History.txt +7 -0
  2. data/README.txt +18 -7
  3. data/Rakefile +72 -0
  4. data/examples/ant/example-build.xml +7 -0
  5. data/examples/appengine/Rakefile +8 -67
  6. data/examples/appengine/Readme +4 -3
  7. data/examples/appengine/lib/duby/appengine_tasks.rb +173 -0
  8. data/examples/appengine/lib/duby/plugin/datastore.rb +92 -31
  9. data/examples/appengine/lib/duby_task.rb +61 -0
  10. data/examples/appengine/src/com/ribrdb/DubyApp.duby +32 -6
  11. data/examples/appengine/src/com/ribrdb/list.dhtml +2 -2
  12. data/examples/appengine/{config.ru → src/config.ru} +0 -0
  13. data/examples/bintrees.duby +66 -0
  14. data/examples/dynamic.duby +17 -0
  15. data/examples/fib.duby +3 -11
  16. data/examples/fields.duby +3 -3
  17. data/examples/fractal.duby +1 -3
  18. data/examples/sort_closure.duby +7 -0
  19. data/examples/swing.duby +11 -11
  20. data/javalib/duby-bootstrap.jar +0 -0
  21. data/javalib/dynalang-invoke-0.1.jar +0 -0
  22. data/lib/duby.rb +168 -35
  23. data/lib/duby/ast.rb +224 -27
  24. data/lib/duby/ast/call.rb +85 -25
  25. data/lib/duby/ast/class.rb +112 -28
  26. data/lib/duby/ast/flow.rb +65 -44
  27. data/lib/duby/ast/intrinsics.rb +223 -21
  28. data/lib/duby/ast/literal.rb +67 -16
  29. data/lib/duby/ast/local.rb +36 -40
  30. data/lib/duby/ast/method.rb +83 -67
  31. data/lib/duby/ast/structure.rb +105 -23
  32. data/lib/duby/compiler.rb +83 -28
  33. data/lib/duby/env.rb +33 -0
  34. data/lib/duby/jvm/base.rb +210 -0
  35. data/lib/duby/jvm/compiler.rb +293 -219
  36. data/lib/duby/jvm/method_lookup.rb +77 -67
  37. data/lib/duby/jvm/source_compiler.rb +250 -157
  38. data/lib/duby/jvm/source_generator/builder.rb +53 -49
  39. data/lib/duby/jvm/source_generator/loops.rb +9 -9
  40. data/lib/duby/jvm/source_generator/precompile.rb +35 -25
  41. data/lib/duby/jvm/typer.rb +19 -10
  42. data/lib/duby/jvm/types.rb +127 -68
  43. data/lib/duby/jvm/types/basic_types.rb +26 -13
  44. data/lib/duby/jvm/types/enumerable.rb +6 -4
  45. data/lib/duby/jvm/types/factory.rb +49 -13
  46. data/lib/duby/jvm/types/floats.rb +16 -0
  47. data/lib/duby/jvm/types/integers.rb +63 -2
  48. data/lib/duby/jvm/types/intrinsics.rb +43 -21
  49. data/lib/duby/jvm/types/methods.rb +326 -86
  50. data/lib/duby/jvm/types/number.rb +3 -0
  51. data/lib/duby/nbcompiler.rb +1 -1
  52. data/lib/duby/plugin/edb.rb +1 -1
  53. data/lib/duby/plugin/java.rb +10 -1
  54. data/lib/duby/transform.rb +134 -46
  55. data/lib/duby/typer.rb +75 -50
  56. data/test/test_ast.rb +106 -106
  57. data/test/test_compilation.rb +46 -32
  58. data/test/test_env.rb +42 -0
  59. data/test/test_java_typer.rb +35 -51
  60. data/test/test_javac_compiler.rb +4 -1
  61. data/test/test_jvm_compiler.rb +564 -133
  62. data/test/test_typer.rb +68 -92
  63. metadata +37 -21
  64. data/examples/README +0 -16
  65. data/lib/duby/c/compiler.rb +0 -134
  66. data/lib/duby/old/compiler_old.rb +0 -845
  67. data/lib/duby/old/declaration.rb +0 -72
  68. data/lib/duby/old/mapper.rb +0 -72
  69. data/lib/duby/old/signature.rb +0 -52
  70. data/lib/duby/old/typer_old.rb +0 -163
  71. data/lib/duby/plugin/math.rb +0 -84
  72. data/test/test_math_plugin.rb +0 -87
@@ -0,0 +1,61 @@
1
+ require 'duby'
2
+ module Duby
3
+ def self.source_path
4
+ @source_path ||= File.expand_path('.')
5
+ end
6
+
7
+ def self.source_path=(path)
8
+ @source_path = File.expand_path(path)
9
+ end
10
+
11
+ def self.dest_path
12
+ @dest_path ||= File.expand_path('.')
13
+ end
14
+
15
+ def self.dest_path=(path)
16
+ @dest_path = File.expand_path(path)
17
+ end
18
+
19
+ def self.dest_to_source_path(path)
20
+ source = File.expand_path(path).sub(/\.(?:java|class)/, '.duby')
21
+ source = source.sub(/^#{dest_path}\//, "#{source_path}/")
22
+ down = source[0,1].downcase + source[1,source.size]
23
+ return down if File.exist?(down)
24
+ source
25
+ end
26
+
27
+ def self.compiler_options
28
+ @compiler_options ||= []
29
+ end
30
+
31
+ def self.compiler_options=(args)
32
+ @compiler_options = args
33
+ end
34
+ end
35
+
36
+ def dubyc(*files)
37
+ if files[-1].kind_of?(Hash)
38
+ options = files.pop
39
+ else
40
+ options = {}
41
+ end
42
+ source_dir = options.fetch(:dir, Duby.source_path)
43
+ dest = options.fetch(:dest, Duby.dest_path)
44
+ files = files.map {|f| f.sub(/^#{source_dir}\//, '')}
45
+ flags = options.fetch(:options, Duby.compiler_options)
46
+ args = ['-d', dest, *flags] + files
47
+ chdir(source_dir) do
48
+ puts $CLASSPATH.inspect
49
+ puts "dubyc #{args.join ' '}"
50
+ Duby.compile(*args)
51
+ Duby.reset
52
+ end
53
+ end
54
+
55
+ rule '.java' => [proc {|n| Duby.dest_to_source_path(n)}] do |t|
56
+ dubyc(t.source, :options=>['-java'])
57
+ end
58
+
59
+ rule '.class' => [proc {|n| Duby.dest_to_source_path(n)}] do |t|
60
+ dubyc(t.source)
61
+ end
@@ -1,28 +1,54 @@
1
1
  import javax.servlet.http.HttpServlet
2
2
  import com.google.appengine.ext.duby.db.Model
3
+ import java.util.HashMap
4
+ import java.util.regex.Pattern
3
5
 
4
6
  class Post < Model
5
- def initialize; end
6
-
7
7
  property title, String
8
8
  property body, Text
9
9
  end
10
10
 
11
11
  class DubyApp < HttpServlet
12
12
  def_edb(list, 'com/ribrdb/list.dhtml')
13
-
13
+
14
14
  def doGet(request, response)
15
- returns :void
16
15
  @posts = Post.all.run
17
16
  response.getWriter.write(list)
18
17
  end
19
-
18
+
20
19
  def doPost(request, response)
21
20
  post = Post.new
22
21
  post.title = request.getParameter('title')
23
- post.body = Text.new(request.getParameter('body'))
22
+ post.body = request.getParameter('body')
24
23
  post.save
25
24
  doGet(request, response)
26
25
  end
27
26
 
27
+
28
+ def initialize
29
+ @escape_pattern = Pattern.compile("[<>&'\"]")
30
+ @escaped = HashMap.new
31
+ @escaped.put("<", "&lt;")
32
+ @escaped.put(">", "&gt;")
33
+ @escaped.put("&", "&amp;")
34
+ @escaped.put("\"", "&quot;")
35
+ @escaped.put("'", "&#39;")
36
+ end
37
+
38
+ def h(text:String)
39
+ return "" unless text
40
+ matcher = @escape_pattern.matcher(text)
41
+ buffer = StringBuffer.new
42
+ while matcher.find
43
+ replacement = String(@escaped.get(matcher.group))
44
+ matcher.appendReplacement(buffer, replacement)
45
+ end
46
+ matcher.appendTail(buffer)
47
+ return buffer.toString
48
+ end
49
+
50
+ def h(o:Object)
51
+ return "" unless o
52
+ h(o.toString)
53
+ end
28
54
  end
@@ -2,8 +2,8 @@
2
2
  <body>
3
3
  <h1>All Posts:</h1>
4
4
  <% for post in @posts %>
5
- <h2><%= post.title %></h2>
6
- <p><%= post.body.getValue %></p>
5
+ <h2><%=h post.title %></h2>
6
+ <p><%=h post.body %></p>
7
7
  <% end %>
8
8
  <hr>
9
9
  <h1>New Post:</h1>
@@ -0,0 +1,66 @@
1
+ class BinaryTrees
2
+ def self.main(args:String[])
3
+ n = 0
4
+ n = Integer.parseInt(args[0]) if args.length > 0
5
+
6
+ maxDepth = (6 > n) ? 6 : n
7
+ stretchDepth = maxDepth + 1
8
+
9
+ check = TreeNode.bottomUpTree(0, stretchDepth).itemCheck
10
+ puts "stretch tree of depth #{stretchDepth}\t check: #{check}"
11
+
12
+ longLivedTree = TreeNode.bottomUpTree 0, maxDepth
13
+
14
+ depth = 4
15
+ while depth <= maxDepth
16
+ iterations = 1 << (maxDepth - depth + 4)
17
+ check = 0
18
+
19
+ i = 1
20
+ while i <= iterations
21
+ check += TreeNode.bottomUpTree(i, depth).itemCheck
22
+ check += TreeNode.bottomUpTree(-i,depth).itemCheck
23
+ i += 1
24
+ end
25
+
26
+ puts "#{iterations * 2}\t trees of depth #{depth}\t check: #{check}"
27
+ depth += 2
28
+ end
29
+
30
+ puts "long lived tree of depth #{maxDepth}\t check: #{longLivedTree.itemCheck}"
31
+ end
32
+ end
33
+
34
+ class TreeNode
35
+ def initialize(left:TreeNode, right:TreeNode, item:int)
36
+ @item = item
37
+ @left = left
38
+ @right = right
39
+ end
40
+
41
+ def initialize(item:int)
42
+ @left = TreeNode(nil)
43
+ @right = TreeNode(nil)
44
+ @item = item
45
+ end
46
+
47
+ def self.bottomUpTree(item:int, depth:int)
48
+ if depth > 0
49
+ TreeNode.new(
50
+ TreeNode.bottomUpTree(2*item-1, depth-1),
51
+ TreeNode.bottomUpTree(2*item, depth-1),
52
+ item)
53
+ else
54
+ TreeNode.new(item)
55
+ end
56
+ end
57
+
58
+ def itemCheck
59
+ # if necessary deallocate here
60
+ if @left == nil
61
+ @item
62
+ else
63
+ @item + @left.itemCheck - @right.itemCheck
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,17 @@
1
+ # Example of using a dynamic type in a method definition
2
+ def foo(a:dynamic)
3
+ puts "I got a #{a.getClass.getName} of size #{a.size}"
4
+ end
5
+
6
+ class SizeThing
7
+ def initialize(size:int)
8
+ @size = size
9
+ end
10
+
11
+ def size
12
+ @size
13
+ end
14
+ end
15
+
16
+ foo([1,2,3])
17
+ foo(SizeThing.new(12))
@@ -1,5 +1,3 @@
1
- import "java.lang.System"
2
-
3
1
  def fib(a:int)
4
2
  if a < 2
5
3
  a
@@ -8,17 +6,11 @@ def fib(a:int)
8
6
  end
9
7
  end
10
8
 
11
- def bench(times:int)
12
- while times > 0
9
+ def bench(n:int)
10
+ n.times do
13
11
  time_start = System.currentTimeMillis
14
- puts "fib(45):"
15
- puts fib(45)
16
- time_total = System.currentTimeMillis - time_start
17
- puts "Total time:"
18
- puts time_total
19
- times -= 1
12
+ puts "fib(45): #{fib(45)}\nTotal time: #{System.currentTimeMillis - time_start}"
20
13
  end
21
- nil
22
14
  end
23
15
 
24
16
  bench 10
@@ -2,10 +2,10 @@ import 'java.util.ArrayList'
2
2
 
3
3
  class Bar
4
4
  def initialize
5
- @a = ArrayList
5
+ @a = ArrayList(nil)
6
6
  end
7
7
 
8
- def list=(a:ArrayList)
8
+ def list(a:ArrayList)
9
9
  @a = a
10
10
  end
11
11
 
@@ -18,5 +18,5 @@ b = Bar.new
18
18
  list = ArrayList.new
19
19
  list.add('hello')
20
20
  list.add('world')
21
- b.list = list
21
+ b.list(list)
22
22
  b.foo
@@ -1,5 +1,3 @@
1
- import java.lang.System
2
-
3
1
  def run
4
2
  puts "Rendering"
5
3
  y = -39.0
@@ -52,6 +50,6 @@ i = 0
52
50
  while i < 10
53
51
  start = System.currentTimeMillis
54
52
  run
55
- puts "Time: " + (System.currentTimeMillis - start) / 1000.0
53
+ puts "Time: #{(System.currentTimeMillis - start) / 1000.0}"
56
54
  i += 1
57
55
  end
@@ -0,0 +1,7 @@
1
+ import java.util.Collections
2
+ import java.util.ArrayList
3
+
4
+ list = ArrayList.new [9,5,2,6,8,5,0,3,6,1,8,3,6,4,7,5,0,8,5,6,7,2,3]
5
+ puts "unsorted: #{list}"
6
+ Collections.sort(list) {|a,b| Integer(a).compareTo(b)}
7
+ puts "sorted: #{list}"
@@ -1,20 +1,20 @@
1
1
  import javax.swing.JFrame
2
2
  import javax.swing.JButton
3
- import java.awt.event.ActionListener
4
3
 
5
- frame = JFrame.new "Welcome to Duby"
6
- frame.setSize 300, 300
7
- frame.setVisible true
4
+ # FIXME blocks need to be inside a MethodDefinition, but main doesn't
5
+ # have one.
6
+ def self.run
7
+ frame = JFrame.new "Welcome to Duby"
8
+ frame.setSize 300, 300
9
+ frame.setVisible true
8
10
 
9
- button = JButton.new "Press me"
10
- frame.add button
11
- frame.show
11
+ button = JButton.new "Press me"
12
+ frame.add button
13
+ frame.show
12
14
 
13
- class AL; implements ActionListener
14
- def initialize; end
15
- def actionPerformed(event)
15
+ button.addActionListener do |event|
16
16
  JButton(event.getSource).setText "Duby Rocks!"
17
17
  end
18
18
  end
19
19
 
20
- button.addActionListener AL.new
20
+ run
@@ -1,8 +1,10 @@
1
1
  require 'fileutils'
2
+ require 'rbconfig'
2
3
  require 'duby/transform'
3
4
  require 'duby/ast'
4
5
  require 'duby/typer'
5
6
  require 'duby/compiler'
7
+ require 'duby/env'
6
8
  begin
7
9
  require 'bitescript'
8
10
  rescue LoadError
@@ -18,42 +20,130 @@ module Duby
18
20
  def self.run(*args)
19
21
  DubyImpl.new.run(*args)
20
22
  end
21
-
23
+
22
24
  def self.compile(*args)
23
25
  DubyImpl.new.compile(*args)
24
26
  end
25
-
27
+
26
28
  def self.parse(*args)
27
29
  DubyImpl.new.parse(*args)
28
30
  end
31
+
32
+ def self.plugins
33
+ @plugins ||= []
34
+ end
35
+
36
+ def self.reset
37
+ @plugins.each {|x| x.reset if x.respond_to?(:reset)}
38
+ end
39
+
40
+ def self.print_error(message, position)
41
+ puts "#{position.file}:#{position.start_line + 1}: #{message}"
42
+ file_offset = 0
43
+ startline = position.start_line
44
+ endline = position.end_line
45
+ start_offset = position.start_offset
46
+ end_offset = position.end_offset
47
+ # don't try to search dash_e
48
+ # TODO: show dash_e source the same way
49
+ if File.exist? position.file
50
+ File.open(position.file).each_with_index do |line, lineno|
51
+ line_end = file_offset + line.size
52
+ skip = [start_offset - file_offset, line.size].min
53
+ if lineno >= startline && lineno <= endline
54
+ puts line.chomp
55
+ if skip > 0
56
+ print ' ' * (skip)
57
+ else
58
+ skip = 0
59
+ end
60
+ if line_end <= end_offset
61
+ puts '^' * (line.size - skip)
62
+ else
63
+ puts '^' * [end_offset - skip - file_offset, 1].max
64
+ end
65
+ end
66
+ file_offset = line_end
67
+ end
68
+ end
69
+ end
70
+
71
+ class CompilationState
72
+ attr_accessor :verbose, :destination
73
+ end
74
+ end
75
+
76
+ # This is a custom classloader impl to allow loading classes with
77
+ # interdependencies by having findClass retrieve classes as needed from the
78
+ # collection of all classes generated by the target script.
79
+ class DubyClassLoader < java::security::SecureClassLoader
80
+ def initialize(parent, class_map)
81
+ super(parent)
82
+ @class_map = class_map
83
+ end
84
+
85
+ def findClass(name)
86
+ if @class_map[name]
87
+ bytes = @class_map[name].to_java_bytes
88
+ defineClass(name, bytes, 0, bytes.length)
89
+ else
90
+ raise java.lang.ClassNotFoundException.new(name)
91
+ end
92
+ end
93
+
94
+ def loadClass(name, resolve)
95
+ cls = findLoadedClass(name)
96
+ if cls == nil
97
+ if @class_map[name]
98
+ cls = findClass(name)
99
+ else
100
+ cls = super(name, false)
101
+ end
102
+ end
103
+
104
+ resolveClass(cls) if resolve
105
+
106
+ cls
107
+ end
29
108
  end
30
109
 
31
110
  class DubyImpl
32
111
  def run(*args)
33
112
  ast = parse(*args)
113
+ main = nil
114
+ class_map = {}
34
115
 
35
- main_cls = nil
116
+ # generate all bytes for all classes
36
117
  compile_ast(ast) do |outfile, builder|
37
118
  bytes = builder.generate
38
119
  name = builder.class_name.gsub(/\//, '.')
39
- cls = JRuby.runtime.jruby_class_loader.define_class(name, bytes.to_java_bytes)
40
- proxy_cls = JavaUtilities.get_proxy_class(name)
120
+ class_map[name] = bytes
121
+ end
122
+
123
+ # load all classes
124
+ dcl = DubyClassLoader.new(java.lang.ClassLoader.system_class_loader, class_map)
125
+ class_map.each do |name,|
126
+ cls = dcl.load_class(name)
41
127
  # TODO: using first main; find correct one
42
- if proxy_cls.respond_to? :main
43
- main_cls ||= proxy_cls
44
- end
128
+ main ||= cls.get_method("main", java::lang::String[].java_class) #rescue nil
45
129
  end
46
-
47
- if main_cls
48
- main_cls.main(args.to_java(:string))
130
+
131
+ # run the main method we found
132
+ if main
133
+ begin
134
+ main.invoke(nil, [args.to_java(:string)].to_java)
135
+ rescue java.lang.Exception => e
136
+ e = e.cause if e.cause
137
+ raise e
138
+ end
49
139
  else
50
140
  puts "No main found"
51
141
  end
52
142
  end
53
-
143
+
54
144
  def compile(*args)
55
145
  process_flags!(args)
56
-
146
+
57
147
  expand_files(args).each do |duby_file|
58
148
  if duby_file == '-e'
59
149
  @filename = '-e'
@@ -66,7 +156,7 @@ class DubyImpl
66
156
  exit 1 if @error
67
157
 
68
158
  compile_ast(ast) do |filename, builder|
69
- filename = "#{@dest}#{filename}"
159
+ filename = "#{@state.destination}#{filename}"
70
160
  FileUtils.mkdir_p(File.dirname(filename))
71
161
  bytes = builder.generate
72
162
  File.open(filename, 'w') {|f| f.write(bytes)}
@@ -79,19 +169,29 @@ class DubyImpl
79
169
  process_flags!(args)
80
170
  @filename = args.shift
81
171
 
82
- if @filename == '-e'
83
- @filename = 'dash_e'
84
- src = args[0]
172
+ if @filename
173
+ if @filename == '-e'
174
+ @filename = 'DashE'
175
+ src = args[0]
176
+ else
177
+ src = File.read(@filename)
178
+ end
85
179
  else
86
- src = File.read(@filename)
180
+ print_help
181
+ exit(1)
87
182
  end
88
183
  Duby::AST.type_factory = Duby::JVM::Types::TypeFactory.new(@filename)
89
- ast = Duby::AST.parse_ruby(src, @filename)
90
- @transformer = Duby::Transform::Transformer.new
184
+ begin
185
+ ast = Duby::AST.parse_ruby(src, @filename)
186
+ rescue org.jrubyparser.lexer.SyntaxException => ex
187
+ Duby.print_error(ex.message, ex.position)
188
+ raise ex if @state.verbose
189
+ end
190
+ @transformer = Duby::Transform::Transformer.new(@state)
91
191
  ast = @transformer.transform(ast, nil)
92
192
  @transformer.errors.each do |ex|
93
- raise ex.cause || ex if @verbose
94
- puts "#@filename:#{ex.position.start_line+1}: #{ex.message}"
193
+ Duby.print_error(ex.message, ex.position)
194
+ raise ex.cause || ex if @state.verbose
95
195
  end
96
196
  @error = @transformer.errors.size > 0
97
197
  ast
@@ -101,11 +201,18 @@ class DubyImpl
101
201
  typer = Duby::Typer::JVM.new(@filename, @transformer)
102
202
  typer.infer(ast)
103
203
  begin
104
- typer.resolve(true)
204
+ typer.resolve(false)
105
205
  ensure
106
- typer.errors.each do |ex|
107
- puts ex.message
108
- puts ex.backtrace if @verbose
206
+ puts ast.inspect if @state.verbose
207
+
208
+ failed = !typer.errors.empty?
209
+ if failed
210
+ puts "Inference Error:"
211
+ typer.errors.each do |ex|
212
+ Duby.print_error(ex.message, ex.node.position)
213
+ puts ex.backtrace if @state.verbose
214
+ end
215
+ exit 1
109
216
  end
110
217
  end
111
218
 
@@ -115,35 +222,61 @@ class DubyImpl
115
222
  end
116
223
 
117
224
  def process_flags!(args)
118
- while args.length > 0
225
+ @state ||= Duby::CompilationState.new
226
+ while args.length > 0 && args[0] =~ /^-/
119
227
  case args[0]
120
- when '-V'
228
+ when '--verbose', '-V'
121
229
  Duby::Typer.verbose = true
122
230
  Duby::AST.verbose = true
123
231
  Duby::Compiler::JVM.verbose = true
124
- @verbose = true
232
+ @state.verbose = true
125
233
  args.shift
126
- when '-java'
234
+ when '--java', '-j'
127
235
  require 'duby/jvm/source_compiler'
128
236
  @compiler_class = Duby::Compiler::JavaSource
129
237
  args.shift
130
- when '-d'
238
+ when '--dest', '-d'
239
+ args.shift
240
+ @state.destination = File.join(File.expand_path(args.shift), '')
241
+ when '--cd'
131
242
  args.shift
132
- @dest = File.join(args.shift, '')
133
- when '-p'
243
+ Dir.chdir(args.shift)
244
+ when '--plugin', '-p'
134
245
  args.shift
135
246
  plugin = args.shift
136
247
  require "duby/plugin/#{plugin}"
137
248
  when '-I'
138
249
  args.shift
139
250
  $: << args.shift
140
- else
251
+ when '--classpath', '-c'
252
+ args.shift
253
+ Duby::Env.decode_paths(args.shift, $CLASSPATH)
254
+ when '--help', '-h'
255
+ print_help
256
+ exit(0)
257
+ when '-e'
141
258
  break
259
+ else
260
+ puts "unrecognized flag: " + args[0]
261
+ print_help
262
+ exit(1)
142
263
  end
143
264
  end
265
+ @state.destination ||= File.join(File.expand_path('.'), '')
144
266
  @compiler_class ||= Duby::Compiler::JVM
145
267
  end
146
-
268
+
269
+ def print_help
270
+ $stdout.print "#{$0} [flags] <files or \"-e SCRIPT\">
271
+ -V, --verbose\t\tVerbose logging
272
+ -j, --java\t\tOutput .java source (jrubyc only)
273
+ -d, --dir DIR\t\tUse DIR as the base dir for compilation, packages
274
+ -p, --plugin PLUGIN\tLoad and use plugin during compilation
275
+ -c, --classpath PATH\tAdd PATH to the Java classpath for compilation
276
+ -h, --help\t\tPrint this help message
277
+ -e\t\t\tCompile or run the script following -e (naming it \"DashE\")"
278
+ end
279
+
147
280
  def expand_files(files)
148
281
  expanded = []
149
282
  files.each do |filename|