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,13 @@
1
+ import "java.lang.System"
2
+
3
+ def foo
4
+ home = System.getProperty "java.home"
5
+ System.setProperty "hello.world", "something"
6
+ hello = System.getProperty "hello.world"
7
+
8
+ puts home
9
+ puts hello
10
+ end
11
+
12
+ puts "Hello world!"
13
+ foo
@@ -0,0 +1,12 @@
1
+ class Foo
2
+ def initialize
3
+ puts 'constructor'
4
+ @hello = 'Hello, '
5
+ end
6
+
7
+ def hello(a:string)
8
+ puts @hello; puts a
9
+ end
10
+ end
11
+
12
+ Foo.new.hello('Duby')
@@ -0,0 +1,20 @@
1
+ import javax.swing.JFrame
2
+ import javax.swing.JButton
3
+ import java.awt.event.ActionListener
4
+
5
+ frame = JFrame.new "Welcome to Duby"
6
+ frame.setSize 300, 300
7
+ frame.setVisible true
8
+
9
+ button = JButton.new "Press me"
10
+ frame.add button
11
+ frame.show
12
+
13
+ class AL; implements ActionListener
14
+ def initialize; end
15
+ def actionPerformed(event)
16
+ JButton(event.getSource).setText "Duby Rocks!"
17
+ end
18
+ end
19
+
20
+ button.addActionListener AL.new
@@ -0,0 +1,15 @@
1
+ def tak(x:fixnum, y:fixnum, z:fixnum)
2
+ unless y < x
3
+ z
4
+ else
5
+ tak( tak(x-1, y, z),
6
+ tak(y-1, z, x),
7
+ tak(z-1, x, y))
8
+ end
9
+ end
10
+
11
+ i = 0
12
+ while i<1000
13
+ tak(24, 16, 8)
14
+ i+=1
15
+ end
Binary file
@@ -0,0 +1,170 @@
1
+ require 'fileutils'
2
+ require 'duby/transform'
3
+ require 'duby/ast'
4
+ require 'duby/typer'
5
+ require 'duby/compiler'
6
+ begin
7
+ require 'bitescript'
8
+ rescue LoadError
9
+ $: << File.dirname(__FILE__) + '/../../bitescript/lib'
10
+ require 'bitescript'
11
+ end
12
+ require 'duby/jvm/compiler'
13
+ require 'duby/jvm/typer'
14
+ Dir[File.dirname(__FILE__) + "/duby/plugin/*"].each {|file| require "#{file}" if file =~ /\.rb$/}
15
+ require 'jruby'
16
+
17
+ module Duby
18
+ VERSION = '0.0.1'
19
+
20
+ def self.run(*args)
21
+ DubyImpl.new.run(*args)
22
+ end
23
+
24
+ def self.compile(*args)
25
+ DubyImpl.new.compile(*args)
26
+ end
27
+
28
+ def self.parse(*args)
29
+ DubyImpl.new.parse(*args)
30
+ end
31
+ end
32
+
33
+ class DubyImpl
34
+ def run(*args)
35
+ ast = parse(*args)
36
+
37
+ main_cls = nil
38
+ compile_ast(ast) do |outfile, builder|
39
+ bytes = builder.generate
40
+ name = builder.class_name.gsub(/\//, '.')
41
+ cls = JRuby.runtime.jruby_class_loader.define_class(name, bytes.to_java_bytes)
42
+ proxy_cls = JavaUtilities.get_proxy_class(name)
43
+ # TODO: using first main; find correct one
44
+ if proxy_cls.respond_to? :main
45
+ main_cls ||= proxy_cls
46
+ end
47
+ end
48
+
49
+ if main_cls
50
+ main_cls.main(args.to_java(:string))
51
+ else
52
+ puts "No main found"
53
+ end
54
+ end
55
+
56
+ def compile(*args)
57
+ process_flags!(args)
58
+
59
+ expand_files(args).each do |duby_file|
60
+ if duby_file == '-e'
61
+ @filename = '-e'
62
+ next
63
+ elsif @filename == '-e'
64
+ ast = parse('-e', duby_file)
65
+ else
66
+ ast = parse(duby_file)
67
+ end
68
+ exit 1 if @error
69
+
70
+ compile_ast(ast) do |filename, builder|
71
+ filename = "#{@dest}#{filename}"
72
+ FileUtils.mkdir_p(File.dirname(filename))
73
+ bytes = builder.generate
74
+ File.open(filename, 'w') {|f| f.write(bytes)}
75
+ end
76
+ @filename = nil
77
+ end
78
+ end
79
+
80
+ def parse(*args)
81
+ process_flags!(args)
82
+ @filename = args.shift
83
+
84
+ if @filename == '-e'
85
+ @filename = 'dash_e'
86
+ src = args[0]
87
+ else
88
+ src = File.read(@filename)
89
+ end
90
+ Duby::AST.type_factory = Duby::JVM::Types::TypeFactory.new(@filename)
91
+ ast = Duby::AST.parse_ruby(src, @filename)
92
+ @transformer = Duby::Transform::Transformer.new
93
+ ast = @transformer.transform(ast, nil)
94
+ @transformer.errors.each do |ex|
95
+ raise ex.cause || ex if @verbose
96
+ puts "#@filename:#{ex.position.start_line+1}: #{ex.message}"
97
+ end
98
+ @error = @transformer.errors.size > 0
99
+ ast
100
+ end
101
+
102
+ def compile_ast(ast, &block)
103
+ typer = Duby::Typer::JVM.new(@filename)
104
+ typer.infer(ast)
105
+ begin
106
+ typer.resolve(true)
107
+ ensure
108
+ typer.errors.each do |ex|
109
+ puts ex.message
110
+ puts ex.backtrace if @verbose
111
+ end
112
+ end
113
+
114
+ compiler = @compiler_class.new(@filename)
115
+ ast.compile(compiler, false)
116
+ compiler.generate(&block)
117
+ end
118
+
119
+ def process_flags!(args)
120
+ while args.length > 0
121
+ case args[0]
122
+ when '-V'
123
+ Duby::Typer.verbose = true
124
+ Duby::AST.verbose = true
125
+ Duby::Compiler::JVM.verbose = true
126
+ @verbose = true
127
+ args.shift
128
+ when '-java'
129
+ require 'duby/jvm/source_compiler'
130
+ @compiler_class = Duby::Compiler::JavaSource
131
+ args.shift
132
+ when '-d'
133
+ args.shift
134
+ @dest = File.join(args.shift, '')
135
+ when '-p'
136
+ args.shift
137
+ plugin = args.shift
138
+ require "duby/plugin/#{plugin}"
139
+ when '-I'
140
+ args.shift
141
+ $: << args.shift
142
+ else
143
+ break
144
+ end
145
+ end
146
+ @compiler_class ||= Duby::Compiler::JVM
147
+ end
148
+
149
+ def expand_files(files)
150
+ expanded = []
151
+ files.each do |filename|
152
+ if File.directory?(filename)
153
+ Dir[File.join(filename, '*')].each do |child|
154
+ if File.directory?(child)
155
+ files << child
156
+ elsif child =~ /\.duby$/
157
+ expanded << child
158
+ end
159
+ end
160
+ else
161
+ expanded << filename
162
+ end
163
+ end
164
+ expanded
165
+ end
166
+ end
167
+
168
+ if __FILE__ == $0
169
+ Duby.run(ARGV[0], *ARGV[1..-1])
170
+ end
@@ -0,0 +1,340 @@
1
+ require 'duby/transform'
2
+
3
+ module Duby
4
+ module AST
5
+ class << self
6
+ attr_accessor :verbose
7
+ end
8
+
9
+ # The top of the AST class hierarchy, this represents an abstract AST node.
10
+ # It provides accessors for _children_, an array of all child nodes,
11
+ # _parent_, a reference to this node's parent (nil if none), and _newline_,
12
+ # whether this node represents a new line.
13
+ class Node
14
+ attr_accessor :children
15
+ attr_accessor :parent
16
+ attr_accessor :position
17
+ attr_accessor :newline
18
+ attr_accessor :inferred_type
19
+
20
+ def initialize(parent, position, children = [])
21
+ @parent = parent
22
+ @newline = false
23
+ @inferred_type = nil
24
+ @resolved = false
25
+ @position = position
26
+ if block_given?
27
+ @children = yield(self) || []
28
+ else
29
+ @children = children
30
+ end
31
+ end
32
+
33
+ def line_number
34
+ if @position
35
+ @position.start_line + 1
36
+ else
37
+ 0
38
+ end
39
+ end
40
+
41
+ def log(message)
42
+ puts "* [AST] [#{simple_name}] " + message if AST.verbose
43
+ end
44
+
45
+ def inspect(indent = 0)
46
+ indent_str = ' ' * indent
47
+ str = indent_str + to_s
48
+ children.each do |child|
49
+ if child
50
+ if ::Array === child
51
+ child.each {|ary_child|
52
+ str << "\n#{ary_child.inspect(indent + 1)}"
53
+ }
54
+ elsif ::Hash === child
55
+ str << "\n#{indent_str} #{child.inspect}"
56
+ else
57
+ str << "\n#{child.inspect(indent + 1)}"
58
+ end
59
+ end
60
+ end
61
+ str
62
+ end
63
+
64
+ def simple_name
65
+ self.class.name.split("::")[-1]
66
+ end
67
+
68
+ def to_s; simple_name; end
69
+
70
+ def [](index) children[index] end
71
+
72
+ def each(&b) children.each(&b) end
73
+
74
+ def resolved!
75
+ log "#{to_s} resolved!"
76
+ @resolved = true
77
+ end
78
+
79
+ def resolved?; @resolved end
80
+
81
+ def resolve_if(typer)
82
+ unless resolved?
83
+ @inferred_type = yield
84
+ @inferred_type ? resolved! : typer.defer(self)
85
+ end
86
+ @inferred_type
87
+ end
88
+ end
89
+
90
+ class ErrorNode < Node
91
+ def initialize(parent, error)
92
+ super(parent, error.position)
93
+ @error = error
94
+ @inferred_type = TypeReference::ErrorType
95
+ @resolved = true
96
+ end
97
+
98
+ def infer(typer)
99
+ end
100
+ end
101
+
102
+ module Named
103
+ attr_accessor :name
104
+
105
+ def to_s
106
+ "#{super}(#{name})"
107
+ end
108
+ end
109
+
110
+ module Typed
111
+ attr_accessor :type
112
+ end
113
+
114
+ module Valued
115
+ include Typed
116
+ attr_accessor :value
117
+ end
118
+
119
+ module Literal
120
+ include Typed
121
+ attr_accessor :literal
122
+
123
+ def to_s
124
+ "#{super}(#{literal.inspect})"
125
+ end
126
+ end
127
+
128
+ module Scoped
129
+ def scope
130
+ @scope ||= begin
131
+ scope = parent
132
+ raise "No parent for #{self.class.name} at #{line_number}" if scope.nil?
133
+ scope = scope.parent until scope.class.include?(Scope)
134
+ scope
135
+ end
136
+ end
137
+ end
138
+
139
+ module ClassScoped
140
+ def scope
141
+ @scope ||= begin
142
+ scope = parent
143
+ scope = scope.parent until scope.nil? || ClassDefinition === scope
144
+ scope
145
+ end
146
+ end
147
+ end
148
+
149
+ module Scope; end
150
+
151
+ class Colon2 < Node; end
152
+
153
+ class Constant < Node
154
+ include Named
155
+ def initialize(parent, position, name)
156
+ @name = name
157
+ super(parent, position, [])
158
+ end
159
+
160
+ def infer(typer)
161
+ @inferred_type ||= begin
162
+ typer.type_reference(name, false, true)
163
+ end
164
+ end
165
+ end
166
+
167
+ class Self < Node; end
168
+
169
+ class VoidType < Node; end
170
+
171
+ class TypeReference < Node
172
+ include Named
173
+ attr_accessor :array
174
+ alias array? array
175
+ attr_accessor :meta
176
+ alias meta? meta
177
+
178
+ def initialize(name, array = false, meta = false, position=nil)
179
+ super(nil, position)
180
+ @name = name
181
+ @array = array
182
+ @meta = meta
183
+ end
184
+
185
+ def to_s
186
+ "Type(#{name}#{array? ? ' array' : ''}#{meta? ? ' meta' : ''})"
187
+ end
188
+
189
+ def ==(other)
190
+ to_s == other.to_s
191
+ end
192
+
193
+ def eql?(other)
194
+ self == other
195
+ end
196
+
197
+ def hash
198
+ to_s.hash
199
+ end
200
+
201
+ def is_parent(other)
202
+ # default behavior now is to disallow any polymorphic types
203
+ self == other
204
+ end
205
+
206
+ def compatible?(other)
207
+ # default behavior is only exact match right now
208
+ self == other ||
209
+ error? || other.error? ||
210
+ unreachable? || other.unreachable?
211
+ end
212
+
213
+ def iterable?
214
+ array?
215
+ end
216
+
217
+ def component_type
218
+ AST.type(name) if array?
219
+ end
220
+
221
+ def narrow(other)
222
+ # only exact match allowed for now, so narrowing is a noop
223
+ if error? || unreachable?
224
+ other
225
+ else
226
+ self
227
+ end
228
+ end
229
+
230
+ def unmeta
231
+ TypeReference.new(name, array, false)
232
+ end
233
+
234
+ def meta
235
+ TypeReference.new(name, array, true)
236
+ end
237
+
238
+ def error?
239
+ name == :error
240
+ end
241
+
242
+ def unreachable?
243
+ name == :unreachable
244
+ end
245
+
246
+ def primitive?
247
+ true
248
+ end
249
+
250
+ NoType = TypeReference.new(:notype)
251
+ NullType = TypeReference.new(:null)
252
+ ErrorType = TypeReference.new(:error)
253
+ UnreachableType = TypeReference.new(:unreachable)
254
+ end
255
+
256
+ class TypeDefinition < TypeReference
257
+ attr_accessor :superclass, :interfaces
258
+
259
+ def initialize(name, superclass, interfaces)
260
+ super(name, false)
261
+
262
+ @superclass = superclass
263
+ @interfaces = interfaces
264
+ end
265
+ end
266
+
267
+ def self.type_factory
268
+ Thread.current[:ast_type_factory]
269
+ end
270
+
271
+ def self.type_factory=(factory)
272
+ Thread.current[:ast_type_factory] = factory
273
+ end
274
+
275
+ # Shortcut method to construct type references
276
+ def self.type(typesym, array = false, meta = false)
277
+ factory = type_factory
278
+ if factory
279
+ factory.type(typesym, array, meta)
280
+ else
281
+ TypeReference.new(typesym, array, meta)
282
+ end
283
+ end
284
+
285
+ def self.no_type
286
+ factory = type_factory
287
+ if factory
288
+ factory.no_type
289
+ else
290
+ TypeReference::NoType
291
+ end
292
+ end
293
+
294
+ def self.error_type
295
+ TypeReference::ErrorType
296
+ end
297
+
298
+ def self.unreachable_type
299
+ TypeReference::UnreachableType
300
+ end
301
+
302
+ def self.fixnum(parent, position, literal)
303
+ factory = type_factory
304
+ if factory
305
+ factory.fixnum(parent, position, literal)
306
+ else
307
+ Fixnum.new(parent, position, literal)
308
+ end
309
+ end
310
+
311
+ def self.float(parent, position, literal)
312
+ factory = type_factory
313
+ if factory
314
+ factory.float(parent, position, literal)
315
+ else
316
+ Float.new(parent, position, literal)
317
+ end
318
+ end
319
+
320
+ def self.defmacro(name, &block)
321
+ @macros ||= {}
322
+ raise "Conflicting macros for #{name}" if @macros[name]
323
+ @macros[name] = block
324
+ end
325
+
326
+ def self.macro(name)
327
+ @macros[name]
328
+ end
329
+ end
330
+ end
331
+
332
+ require 'duby/ast/local'
333
+ require 'duby/ast/call'
334
+ require 'duby/ast/flow'
335
+ require 'duby/ast/literal'
336
+ require 'duby/ast/method'
337
+ require 'duby/ast/class'
338
+ require 'duby/ast/structure'
339
+ require 'duby/ast/type'
340
+ require 'duby/ast/intrinsics'