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,359 @@
1
+ require 'duby/ast'
2
+ require 'duby/transform'
3
+
4
+ module Duby
5
+ module Typer
6
+ class << self
7
+ attr_accessor :verbose
8
+
9
+ def log(message)
10
+ puts "* [#{name}] #{message}" if Typer.verbose
11
+ end
12
+ end
13
+
14
+ class InferenceError < Exception
15
+ attr_accessor :node
16
+ def initialize(msg, node = nil)
17
+ super(msg)
18
+ @node = node
19
+ end
20
+ end
21
+
22
+ class BaseTyper
23
+ include Duby
24
+
25
+ def log(message); Typer.log(message); end
26
+
27
+ def to_s
28
+ name
29
+ end
30
+ end
31
+
32
+ class Simple < BaseTyper
33
+ attr_accessor :known_types, :errors
34
+
35
+ def initialize(self_type)
36
+ @known_types = {}
37
+
38
+ @known_types["self"] = type_reference(self_type)
39
+ @known_types["fixnum"] = type_reference("fixnum")
40
+ @known_types["float"] = type_reference("float")
41
+ @known_types["string"] = type_reference("string")
42
+ @known_types["boolean"] = type_reference("boolean")
43
+ @errors = []
44
+ end
45
+
46
+ def name
47
+ "Simple"
48
+ end
49
+
50
+ def self_type
51
+ known_types["self"]
52
+ end
53
+
54
+ def default_type
55
+ nil
56
+ end
57
+
58
+ def fixnum_type
59
+ known_types["fixnum"]
60
+ end
61
+
62
+ def float_type
63
+ known_types["float"]
64
+ end
65
+
66
+ def string_type
67
+ known_types["string"]
68
+ end
69
+
70
+ def boolean_type
71
+ known_types["boolean"]
72
+ end
73
+
74
+ def null_type
75
+ AST::TypeReference::NullType
76
+ end
77
+
78
+ def no_type
79
+ AST::TypeReference::NoType
80
+ end
81
+
82
+ def define_type(name, superclass, interfaces)
83
+ log "New type defined: '#{name}' < '#{superclass}'"
84
+ known_types[name] = type_definition(name, superclass, interfaces)
85
+
86
+ old_self, known_types["self"] = known_types["self"], known_types[name]
87
+ yield
88
+ known_types["self"] = old_self
89
+
90
+ known_types[name]
91
+ end
92
+
93
+ def learn_local_type(scope, name, type)
94
+ log "Learned local type under #{scope} : #{name} = #{type}"
95
+
96
+ # TODO check for compatibility?
97
+ local_type_hash(scope)[name] ||= known_types[type] || type
98
+
99
+ type
100
+ end
101
+
102
+ def local_type(scope, name)
103
+ log "Retrieved local type in #{scope} : #{name} = #{local_type_hash(scope)[name]}"
104
+
105
+ local_type_hash(scope)[name]
106
+ end
107
+
108
+ def local_types
109
+ @local_types ||= {}
110
+ end
111
+
112
+ def local_type_hash(scope)
113
+ local_types[scope] ||= {}
114
+ end
115
+
116
+ def field_types
117
+ @field_types ||= {}
118
+ end
119
+
120
+ def field_type_hash(cls)
121
+ field_types[cls] ||= {}
122
+ end
123
+
124
+ def infer_signature(method_def)
125
+ end
126
+
127
+ def learn_field_type(cls, name, type)
128
+ log "Learned field type under #{cls} : #{name} = #{type}"
129
+
130
+ # TODO check for compatibility?
131
+ field_type_hash(cls)[name] ||= known_types[type] || type
132
+
133
+ type
134
+ end
135
+
136
+ def field_type(cls, name)
137
+ field_type_hash(cls)[name]
138
+ end
139
+
140
+ def learn_method_type(target_type, name, parameter_types, type, exceptions)
141
+ log "Learned method #{name} (#{parameter_types}) on #{target_type} = #{type}"
142
+
143
+ get_method_type_hash(target_type, name, parameter_types)[:type] = known_types[type] || type
144
+
145
+ # if it's any args are imported types, also add a mapping for the expanded name
146
+ imported_types = parameter_types.map {|param| known_types[param] || param}
147
+ get_method_type_hash(target_type, name, imported_types)[:type] = type
148
+ end
149
+
150
+ def method_type(target_type, name, parameter_types)
151
+ if (target_type && target_type.error?) ||
152
+ parameter_types.any? {|t| t && t.error?}
153
+ return AST.error_type
154
+ end
155
+ constructor = (name == 'new' && target_type && target_type.meta?)
156
+
157
+ if constructor
158
+ # constructor handled different from other methods
159
+ simple_type = get_method_type_hash(target_type.unmeta, 'initialize', parameter_types)[:type]
160
+ else
161
+ simple_type = get_method_type_hash(target_type, name, parameter_types)[:type]
162
+ end
163
+
164
+
165
+ if !simple_type
166
+ log "Method type for \"#{name}\" #{parameter_types} on #{target_type} not found."
167
+
168
+ # allow plugins a go if we're in the inference phase
169
+ simple_type = plugins do |plugin|
170
+ plugin.method_type(self, target_type, name, parameter_types)
171
+ end
172
+ end
173
+
174
+ return nil unless simple_type
175
+
176
+ if constructor
177
+ log "Method type for \"#{name}\" #{parameter_types} on #{target_type} = #{target_type}"
178
+ target_type.unmeta
179
+ else
180
+ log "Method type for \"#{name}\" #{parameter_types} on #{target_type} = #{simple_type}"
181
+ simple_type
182
+ end
183
+ end
184
+
185
+ def plugins
186
+ if cycling?
187
+ Duby.typer_plugins.each do |plugin|
188
+ log "Invoking plugin: #{plugin}"
189
+
190
+ result = yield plugin
191
+ return result if result
192
+ end
193
+ end
194
+
195
+ nil
196
+ end
197
+
198
+ def cycling?
199
+ @cycling
200
+ end
201
+
202
+ def cycling=(c)
203
+ @cycling = c
204
+ end
205
+
206
+ def cycle(count)
207
+ @cycling = true
208
+ count.times do |i|
209
+ begin
210
+ log "[Cycle #{i}]: Started..."
211
+ yield i
212
+ ensure
213
+ log "[Cycle #{i}]: Complete!"
214
+ end
215
+ end
216
+ ensure
217
+ @cycling = false
218
+ end
219
+
220
+ def method_types
221
+ @method_types ||= {}
222
+ end
223
+
224
+ def get_method_type_hash(target_type, name, parameter_types)
225
+ method_types[target_type] ||= {}
226
+ method_types[target_type][name] ||= {}
227
+ method_types[target_type][name][parameter_types.size] ||= {}
228
+
229
+ current = method_types[target_type][name][parameter_types.size]
230
+
231
+ parameter_types.each {|type| current[type] ||= {}; current = current[type]}
232
+
233
+ current
234
+ end
235
+
236
+ def type_reference(name, array=false, meta=false)
237
+ AST::TypeReference.new(name, array, meta)
238
+ end
239
+
240
+ def type_definition(name, superclass, interfaces)
241
+ AST::TypeDefinition.new(name, AST::TypeReference.new(superclass), interfaces)
242
+ end
243
+
244
+ def alias_type(short, long)
245
+ @known_types[type_reference(short, false, false)] = type_reference(long, false, false)
246
+ @known_types[type_reference(short, false, true)] = type_reference(long, false, true)
247
+ end
248
+
249
+ def deferred_nodes
250
+ @deferred_nodes ||= []
251
+ end
252
+
253
+ def infer(node)
254
+ begin
255
+ node.infer(self)
256
+ rescue InferenceError => ex
257
+ ex.node ||= node
258
+ error(node, ex)
259
+ rescue Exception => ex
260
+ error(node, ex.message, ex.backtrace)
261
+ end
262
+ end
263
+
264
+ def error(node, error_or_msg=nil, backtrace=nil)
265
+ if error_or_msg.kind_of? InferenceError
266
+ error = error_or_msg
267
+ elsif error_or_msg
268
+ error = InferenceError.new(error_or_msg, node)
269
+ error.set_backtrace(backtrace) if backtrace
270
+ else
271
+ error = InferenceError.new("Unable to infer type.", node)
272
+ end
273
+ @errors << error
274
+ node.resolve_if(self) do
275
+ AST.error_type
276
+ end
277
+ end
278
+
279
+ def defer(node)
280
+ if @error_next
281
+ log "Marking #{node} as an error"
282
+ @error_next = false
283
+ error(node)
284
+ else
285
+ return if deferred_nodes.include? node
286
+ log "Deferring inference for #{node}"
287
+
288
+ deferred_nodes << node
289
+ end
290
+ end
291
+
292
+ def resolve(raise = false)
293
+ count = deferred_nodes.size + 1
294
+
295
+ log "Entering type inference cycle"
296
+
297
+ retried = false
298
+ cycle(count) do |i|
299
+ old_deferred = @deferred_nodes
300
+ @deferred_nodes = deferred_nodes.select do |node|
301
+ type = infer(node)
302
+
303
+ log "[Cycle #{i}]: Inferred type for #{node}: #{type || 'FAILED'}"
304
+
305
+ type == default_type
306
+ end
307
+
308
+ if @deferred_nodes.size == 0
309
+ log "[Cycle #{i}]: Resolved all types, exiting"
310
+ break
311
+ elsif old_deferred == @deferred_nodes
312
+ if @error_next || retried
313
+ log "[Cycle #{i}]: Made no progress, bailing out"
314
+ break
315
+ else
316
+ # Retry this iteration, and mark the first deferred
317
+ # type as an error.
318
+ retried = true
319
+ @error_next = true
320
+ redo
321
+ end
322
+ end
323
+ retried = false
324
+ end
325
+
326
+ # done with n sweeps, if any remain raise errors
327
+ error_nodes = @errors.map {|e| e.node} + deferred_nodes
328
+ if raise && !error_nodes.empty?
329
+ msg = "Could not infer typing for nodes:"
330
+ error_nodes.map do |e|
331
+ msg << "\n "
332
+ msg << "#{e} at line #{e.line_number} (child of #{e.parent})"
333
+ end
334
+ raise InferenceError.new(msg)
335
+ end
336
+ end
337
+ end
338
+ end
339
+
340
+ def self.typer_plugins
341
+ @typer_plugins ||= []
342
+ end
343
+ end
344
+
345
+ if __FILE__ == $0
346
+ Duby::AST.verbose = true
347
+ Duby::Typer.verbose = true
348
+ ast = Duby::AST.parse(File.read(ARGV[0]))
349
+ typer = Duby::Typer::Simple.new("script")
350
+ typer.infer(ast)
351
+ begin
352
+ typer.resolve(true)
353
+ rescue Duby::Typer::InferenceError => e
354
+ puts e.message
355
+ end
356
+
357
+ puts "\nAST:"
358
+ p ast
359
+ end
@@ -0,0 +1,391 @@
1
+ require 'duby'
2
+ require 'test/unit'
3
+ require 'jruby'
4
+
5
+ class TestAst < Test::Unit::TestCase
6
+ include Duby
7
+
8
+ def test_args
9
+ new_ast = AST.parse("def foo(a, *c, &d); end").body
10
+ arguments = new_ast.arguments
11
+
12
+ assert_not_nil(arguments)
13
+ inspected = "Arguments\n RequiredArgument(a)\n RestArgument(c)\n BlockArgument(d)"
14
+ assert_equal(inspected, arguments.inspect)
15
+
16
+ assert(AST::Arguments === arguments)
17
+ children = arguments.children
18
+ assert_not_nil(children)
19
+ assert_equal(4, children.size)
20
+ assert(Array === children[0])
21
+ assert(AST::RequiredArgument === children[0][0])
22
+ assert_equal("a", children[0][0].name)
23
+ assert_equal(arguments, children[0][0].parent)
24
+ assert(AST::RestArgument === children[2])
25
+ assert_equal("c", children[2].name)
26
+ assert_equal(arguments, children[2].parent)
27
+ assert(AST::BlockArgument === children[3])
28
+ assert_equal("d", children[3].name)
29
+ assert_equal(arguments, children[3].parent)
30
+ end
31
+
32
+ def test_locals
33
+ new_ast = AST.parse("a = 1; a").body
34
+
35
+ assert_not_nil(new_ast)
36
+ assert(AST::Body === new_ast)
37
+ inspected = "Body\n LocalAssignment(name = a, scope = Script)\n Fixnum(1)\n Local(name = a, scope = Script)"
38
+ assert_equal(inspected, new_ast.inspect)
39
+ assert(!new_ast.newline)
40
+
41
+ asgn = new_ast[0]
42
+ var = new_ast[1]
43
+
44
+ assert(AST::LocalAssignment === asgn)
45
+ assert(asgn.newline)
46
+ assert_equal("a", asgn.name)
47
+ assert(AST::Fixnum === asgn.value)
48
+ assert(!asgn.value.newline)
49
+ assert(AST::Local === var)
50
+ assert(var.newline)
51
+ assert_equal("a", var.name)
52
+ end
53
+
54
+ def test_fields
55
+ new_ast = AST.parse("@a = 1; @a").body
56
+
57
+ assert_not_nil(new_ast)
58
+ assert(AST::Body === new_ast)
59
+ inspected = "Body\n FieldAssignment(@a)\n Fixnum(1)\n Field(@a)"
60
+ assert_equal(inspected, new_ast.inspect)
61
+ assert(!new_ast.newline)
62
+
63
+ asgn = new_ast[0]
64
+ var = new_ast[1]
65
+
66
+ assert(AST::FieldAssignment === asgn)
67
+ assert(asgn.newline)
68
+ assert_equal("@a", asgn.name)
69
+ assert(AST::Fixnum === asgn.value)
70
+ assert(!asgn.value.newline)
71
+ assert(AST::Field === var)
72
+ assert(var.newline)
73
+ assert_equal("@a", var.name)
74
+ end
75
+
76
+ def test_array
77
+ new_ast = AST.parse("[a = 1, 1]").body
78
+
79
+ assert_not_nil(new_ast)
80
+ assert(AST::Array === new_ast)
81
+ assert_equal("Array\n LocalAssignment(name = a, scope = Script)\n Fixnum(1)\n Fixnum(1)", new_ast.inspect)
82
+
83
+ assert(AST::LocalAssignment === new_ast[0])
84
+ assert(AST::Fixnum === new_ast[1])
85
+ end
86
+
87
+ def test_call
88
+ new_ast = AST.parse("1.foo(1)").body
89
+
90
+ assert_not_nil(new_ast)
91
+ assert(AST::Call === new_ast)
92
+ assert_equal("Call(foo)\n Fixnum(1)\n Fixnum(1)", new_ast.inspect)
93
+
94
+ assert_equal("foo", new_ast.name)
95
+ assert(AST::Fixnum === new_ast.target)
96
+ assert_not_nil(new_ast.parameters)
97
+ assert_equal(1, new_ast.parameters.size)
98
+ assert(AST::Fixnum === new_ast.parameters[0])
99
+ end
100
+
101
+ def test_fcall
102
+ new_ast = AST.parse("foo(1)").body
103
+
104
+ assert_not_nil(new_ast)
105
+ assert(AST::FunctionalCall === new_ast)
106
+ assert_equal("FunctionalCall(foo)\n Fixnum(1)", new_ast.inspect)
107
+
108
+ assert_equal("foo", new_ast.name)
109
+ assert_not_nil(new_ast.parameters)
110
+ assert_equal(1, new_ast.parameters.size)
111
+ assert(AST::Fixnum === new_ast.parameters[0])
112
+ end
113
+
114
+ def test_if
115
+ new_ast = AST.parse("if 1; 2; elsif !3; 4; else; 5; end").body
116
+
117
+ assert_not_nil(new_ast)
118
+ assert(AST::If === new_ast)
119
+ assert_equal("If\n Condition\n Fixnum(1)\n Fixnum(2)\n If\n Condition\n Not\n Fixnum(3)\n Fixnum(4)\n Fixnum(5)", new_ast.inspect)
120
+
121
+ assert(AST::Condition === new_ast.condition)
122
+ assert(AST::Fixnum === new_ast.condition.predicate)
123
+ assert(AST::Fixnum === new_ast.body)
124
+ assert(AST::If === new_ast.else)
125
+ assert(AST::Condition === new_ast.else.condition)
126
+ assert(AST::Not === new_ast.else.condition.predicate)
127
+ assert(AST::Fixnum === new_ast.else.body)
128
+ assert(AST::Fixnum === new_ast.else.else)
129
+ end
130
+
131
+ def test_begin
132
+ new_ast = AST.parse("begin; 1; 2; end").body
133
+
134
+ assert_not_nil(new_ast)
135
+ assert_equal("Body\n Fixnum(1)\n Fixnum(2)", new_ast.inspect)
136
+ assert(AST::Body === new_ast)
137
+ assert(AST::Fixnum === new_ast[0])
138
+
139
+ new_ast = AST.parse("begin; 1; end").body
140
+ assert(AST::Fixnum === new_ast)
141
+
142
+ new_ast = AST.parse("begin; end").body
143
+ assert(AST::Noop === new_ast)
144
+ end
145
+
146
+ def test_block
147
+ new_ast = AST.parse("1; 2").body
148
+
149
+ assert_not_nil(new_ast)
150
+ assert_equal("Body\n Fixnum(1)\n Fixnum(2)", new_ast.inspect)
151
+ assert(AST::Body === new_ast)
152
+ assert(AST::Fixnum === new_ast[0])
153
+
154
+ new_ast = AST.parse("1").body
155
+ assert(AST::Fixnum === new_ast)
156
+ end
157
+
158
+ def test_fixnum
159
+ new_ast = AST.parse("1").body
160
+
161
+ assert_not_nil(new_ast)
162
+ assert_equal("Fixnum(1)", new_ast.inspect)
163
+ assert(AST::Fixnum === new_ast)
164
+ assert_equal(1, new_ast.literal)
165
+ end
166
+
167
+ def test_float
168
+ new_ast = AST.parse("1.0").body
169
+
170
+ assert_not_nil(new_ast)
171
+ assert_equal("Float(1.0)", new_ast.inspect)
172
+ assert(AST::Float === new_ast)
173
+ assert_equal(1.0, new_ast.literal)
174
+ end
175
+
176
+ def test_class
177
+ new_ast = AST.parse("class Foo < Bar; 1; 2; end").body
178
+
179
+ assert_not_nil(new_ast)
180
+ assert_equal("ClassDefinition(Foo)\n Type(Bar)\n Body\n Fixnum(1)\n Fixnum(2)", new_ast.inspect)
181
+ assert(AST::ClassDefinition === new_ast)
182
+ assert_equal("Foo", new_ast.name)
183
+
184
+ assert(AST::TypeReference === new_ast.superclass)
185
+ assert(AST::Body === new_ast.body)
186
+ assert(AST::Fixnum === new_ast.body[0])
187
+
188
+ new_ast = AST.parse("class Foo < Bar; def foo; end; end").body
189
+
190
+ assert_not_nil(new_ast)
191
+ assert_equal("ClassDefinition(Foo)\n Type(Bar)\n MethodDefinition(foo)\n {:return=>nil}\n Arguments", new_ast.inspect)
192
+ assert_equal(new_ast, new_ast.body.parent)
193
+ end
194
+
195
+ def test_defn
196
+ new_ast = AST.parse("def foo(a, b); 1; end").body
197
+
198
+ assert_not_nil(new_ast)
199
+ assert_equal("MethodDefinition(foo)\n {:return=>nil}\n Arguments\n RequiredArgument(a)\n RequiredArgument(b)\n Fixnum(1)", new_ast.inspect)
200
+ assert(AST::MethodDefinition === new_ast)
201
+ assert_equal("foo", new_ast.name)
202
+ assert_not_nil(new_ast.signature)
203
+ assert_equal(1, new_ast.signature.size)
204
+ assert(nil === new_ast.signature[:return])
205
+ assert(AST::Arguments === new_ast.arguments)
206
+ assert(AST::Fixnum === new_ast.body)
207
+
208
+ new_ast = AST.parse("def foo; end").body
209
+
210
+ assert_not_nil(new_ast)
211
+ assert_equal("MethodDefinition(foo)\n {:return=>nil}\n Arguments", new_ast.inspect)
212
+ assert_not_nil(new_ast.arguments)
213
+ assert_equal(nil, new_ast.arguments.args)
214
+ assert_equal(nil, new_ast.arguments.opt_args)
215
+ assert_equal(nil, new_ast.arguments.rest_arg)
216
+ assert_equal(nil, new_ast.arguments.block_arg)
217
+ assert_nil(new_ast.body)
218
+ end
219
+
220
+ def test_defs
221
+ new_ast = AST.parse("def self.foo(a, b); 1; end").body
222
+
223
+ assert_not_nil(new_ast)
224
+ inspected = "StaticMethodDefinition(foo)\n {:return=>nil}\n Arguments\n RequiredArgument(a)\n RequiredArgument(b)\n Fixnum(1)"
225
+ assert_equal(inspected, new_ast.inspect)
226
+ assert(AST::StaticMethodDefinition === new_ast)
227
+ assert_equal("foo", new_ast.name)
228
+ assert_not_nil(new_ast.signature)
229
+ assert_equal(1, new_ast.signature.size)
230
+ assert(nil === new_ast.signature[:return])
231
+ assert(AST::Arguments === new_ast.arguments)
232
+ assert(AST::Fixnum === new_ast.body)
233
+
234
+ new_ast = AST.parse("def self.foo; end").body
235
+
236
+ assert_not_nil(new_ast)
237
+ assert_equal("StaticMethodDefinition(foo)\n {:return=>nil}\n Arguments", new_ast.inspect)
238
+ assert_not_nil(new_ast.arguments)
239
+ assert_equal(nil, new_ast.arguments.args)
240
+ assert_equal(nil, new_ast.arguments.opt_args)
241
+ assert_equal(nil, new_ast.arguments.rest_arg)
242
+ assert_equal(nil, new_ast.arguments.block_arg)
243
+ assert_nil(new_ast.body)
244
+ end
245
+
246
+ def test_signature
247
+ new_ast = AST.parse("def self.foo(a, b); {a => :foo, b => :bar, :return => :baz}; 1; end").body
248
+
249
+ assert_not_nil(new_ast.signature)
250
+ inspected = "StaticMethodDefinition(foo)\n {:return=>Type(baz), :a=>Type(foo), :b=>Type(bar)}\n Arguments\n RequiredArgument(a)\n RequiredArgument(b)\n Body\n Noop\n Fixnum(1)"
251
+ assert_equal(inspected, new_ast.inspect)
252
+ signature = new_ast.signature
253
+ assert_equal(3, signature.size)
254
+ assert(AST::TypeReference === signature[:return])
255
+ assert_equal("baz", signature[:return].name)
256
+ assert(AST::TypeReference === signature[:a])
257
+ assert_equal("foo", signature[:a].name)
258
+ assert(AST::TypeReference === signature[:b])
259
+ assert_equal("bar", signature[:b].name)
260
+ end
261
+
262
+ def test_type_reference
263
+ signature = AST.parse_ruby("{a => :foo, b => java.lang.Object, :return => ArrayList}").child_nodes[0].signature(nil)
264
+
265
+ inspected = "{:return=>Type(ArrayList), :a=>Type(foo), :b=>Type(java.lang.Object)}"
266
+ assert_equal(inspected, signature.inspect)
267
+ assert_equal(3, signature.size)
268
+ assert(AST::TypeReference === signature[:return])
269
+ assert_equal("ArrayList", signature[:return].name)
270
+ assert(AST::TypeReference === signature[:a])
271
+ assert_equal("foo", signature[:a].name)
272
+ assert(AST::TypeReference === signature[:b])
273
+ assert_equal("java.lang.Object", signature[:b].name)
274
+ end
275
+
276
+ def test_return
277
+ new_ast = AST.parse("return 1").body
278
+
279
+ assert_not_nil(new_ast)
280
+ inspected = "Return\n Fixnum(1)"
281
+ assert_equal(inspected, new_ast.inspect)
282
+ assert(AST::Return === new_ast)
283
+ assert(AST::Fixnum === new_ast.value)
284
+ end
285
+
286
+ def test_vcall
287
+ new_ast = AST.parse("foo").body
288
+
289
+ assert_not_nil(new_ast)
290
+ assert(AST::FunctionalCall === new_ast)
291
+ assert_equal("FunctionalCall(foo)", new_ast.inspect)
292
+
293
+ assert_equal("foo", new_ast.name)
294
+ assert_not_nil(new_ast.parameters)
295
+ assert_equal(0, new_ast.parameters.size)
296
+ end
297
+
298
+ def test_while
299
+ new_ast = AST.parse("while 1; 2; end").body
300
+
301
+ assert_not_nil(new_ast)
302
+ assert(AST::Loop === new_ast)
303
+ assert_equal("WhileLoop(check_first = true, negative = false)\n Condition\n Fixnum(1)\n Fixnum(2)", new_ast.inspect)
304
+ assert(new_ast.check_first?)
305
+ assert(!new_ast.negative?)
306
+ assert(AST::Condition === new_ast.condition)
307
+ assert(AST::Fixnum === new_ast.condition.predicate)
308
+ assert(AST::Fixnum === new_ast.body)
309
+
310
+ new_ast = AST.parse("begin; 2; end while 1").body
311
+
312
+ assert_not_nil(new_ast)
313
+ assert(AST::Loop === new_ast)
314
+ assert_equal("WhileLoop(check_first = false, negative = false)\n Condition\n Fixnum(1)\n Fixnum(2)", new_ast.inspect)
315
+ assert(!new_ast.check_first?)
316
+ assert(!new_ast.negative?)
317
+ assert(AST::Condition === new_ast.condition)
318
+ assert(AST::Fixnum === new_ast.condition.predicate)
319
+ assert(AST::Fixnum === new_ast.body)
320
+ end
321
+
322
+ def test_until
323
+ new_ast = AST.parse("until 1; 2; end").body
324
+
325
+ assert_not_nil(new_ast)
326
+ assert(AST::Loop === new_ast)
327
+ assert_equal("WhileLoop(check_first = true, negative = true)\n Condition\n Fixnum(1)\n Fixnum(2)", new_ast.inspect)
328
+ assert(new_ast.check_first?)
329
+ assert(new_ast.negative?)
330
+ assert(AST::Condition === new_ast.condition)
331
+ assert(AST::Fixnum === new_ast.condition.predicate)
332
+ assert(AST::Fixnum === new_ast.body)
333
+
334
+ new_ast = AST.parse("begin; 2; end until 1").body
335
+
336
+ assert_not_nil(new_ast)
337
+ assert(AST::Loop === new_ast)
338
+ assert_equal("WhileLoop(check_first = false, negative = true)\n Condition\n Fixnum(1)\n Fixnum(2)", new_ast.inspect)
339
+ assert(!new_ast.check_first?)
340
+ assert(new_ast.negative?)
341
+ assert(AST::Condition === new_ast.condition)
342
+ assert(AST::Fixnum === new_ast.condition.predicate)
343
+ assert(AST::Fixnum === new_ast.body)
344
+ end
345
+
346
+ def test_string
347
+ new_ast = AST.parse("'foo'").body
348
+
349
+ assert_not_nil(new_ast)
350
+ assert(AST::String === new_ast)
351
+ assert_equal("String(\"foo\")", new_ast.inspect)
352
+ assert_equal("foo", new_ast.literal)
353
+ end
354
+
355
+ def test_root
356
+ new_ast = AST.parse("1").body
357
+
358
+ assert_not_nil(new_ast)
359
+ assert(AST::Fixnum === new_ast)
360
+ end
361
+
362
+ def test_boolean
363
+ new_ast1 = AST.parse("true").body
364
+ new_ast2 = AST.parse("false").body
365
+
366
+ assert_not_nil(new_ast1)
367
+ assert_not_nil(new_ast2)
368
+ assert(AST::Boolean === new_ast1)
369
+ assert(AST::Boolean === new_ast2)
370
+ assert(new_ast1.literal)
371
+ assert(!new_ast2.literal)
372
+ end
373
+
374
+ def test_return
375
+ new_ast = AST.parse("return 1").body
376
+
377
+ assert_not_nil(new_ast)
378
+ assert(AST::Return === new_ast)
379
+ assert(AST::Fixnum === new_ast.value)
380
+ assert(1, new_ast.value.literal)
381
+ end
382
+
383
+ def test_empty_array
384
+ new_ast = AST.parse("int[5]").body
385
+
386
+ assert_not_nil(new_ast)
387
+ assert(AST::EmptyArray === new_ast)
388
+ assert_equal(5, new_ast.size.literal)
389
+ assert_equal(AST.type(:int), new_ast.inferred_type)
390
+ end
391
+ end