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,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'