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,98 @@
1
+ require 'duby'
2
+ require 'duby/compiler'
3
+ require 'test/unit'
4
+ require 'jruby'
5
+
6
+ class TestAst < Test::Unit::TestCase
7
+ include Duby
8
+
9
+ class MockCompiler
10
+ attr_accessor :calls
11
+
12
+ def initialize
13
+ @calls = []
14
+ end
15
+ def compile(ast)
16
+ ast.compile(self, true)
17
+ end
18
+
19
+ def line(num)
20
+ # ignore newlines
21
+ end
22
+
23
+ def method_missing(sym, *args, &block)
24
+ calls << [sym, *args]
25
+ block.call if block
26
+ end
27
+ end
28
+
29
+ def setup
30
+ @compiler = MockCompiler.new
31
+ end
32
+
33
+ def test_fixnum
34
+ new_ast = AST.parse("1").body
35
+
36
+ new_ast.compile(@compiler, true)
37
+
38
+ assert_equal([[:fixnum, 1]], @compiler.calls)
39
+ end
40
+
41
+ def test_string
42
+ new_ast = AST.parse("'foo'").body
43
+
44
+ new_ast.compile(@compiler, true)
45
+
46
+ assert_equal([[:string, "foo"]], @compiler.calls)
47
+ end
48
+
49
+ def test_float
50
+ new_ast = AST.parse("1.0").body
51
+
52
+ new_ast.compile(@compiler, true)
53
+
54
+ assert_equal([[:float, 1.0]], @compiler.calls)
55
+ end
56
+
57
+ def test_boolean
58
+ new_ast = AST.parse("true").body
59
+
60
+ new_ast.compile(@compiler, true)
61
+
62
+ assert_equal([[:boolean, true]], @compiler.calls)
63
+ end
64
+
65
+ def test_local
66
+ new_ast = AST.parse("a = 1").body
67
+
68
+ new_ast.compile(@compiler, true)
69
+
70
+ assert_equal([[:local_assign, "a", nil, true, AST.fixnum(nil, nil, 1)]], @compiler.calls)
71
+ end
72
+
73
+ def test_local_typed
74
+ new_ast = AST.parse("a = 1").body
75
+ typer = Typer::Simple.new(:bar)
76
+ new_ast.infer(typer)
77
+ new_ast.compile(@compiler, true)
78
+
79
+ assert_equal([[:local_assign, "a", AST.type(:fixnum), true, AST.fixnum(nil, nil, 1)]], @compiler.calls)
80
+ end
81
+
82
+ def test_return
83
+ new_ast = AST.parse("return 1").body
84
+ new_ast.compile(@compiler, true)
85
+
86
+ assert_equal([[:return, new_ast]], @compiler.calls)
87
+ end
88
+
89
+ def test_empty_array
90
+ new_ast = AST.parse("int[5]").body
91
+ new_ast.compile(@compiler, true)
92
+
93
+ assert_equal(1, @compiler.calls.size)
94
+ size = @compiler.calls[0].pop
95
+ assert_equal([[:empty_array, AST.type(:int)]], @compiler.calls)
96
+ assert_equal(5, size.literal)
97
+ end
98
+ end
@@ -0,0 +1,199 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
2
+
3
+ require 'test/unit'
4
+ require 'duby/typer'
5
+ require 'duby/plugin/java'
6
+ require 'duby/jvm/compiler'
7
+ require 'duby/jvm/typer'
8
+
9
+ class TestJavaTyper < Test::Unit::TestCase
10
+ include Duby
11
+
12
+ def setup
13
+ AST.type_factory = Duby::JVM::Types::TypeFactory.new
14
+ @typer = Typer::JVM.new('foobar')
15
+ compiler = Duby::Compiler::JVM.new('foobar')
16
+
17
+ @java_typer = Typer::JavaTyper.new
18
+ end
19
+
20
+ def teardown
21
+ AST.type_factory = nil
22
+ end
23
+
24
+ def test_simple_overtyped_meta_method
25
+ string_meta = AST::type('java.lang.String', false, true)
26
+ string = AST::type('java.lang.String')
27
+
28
+ # integral types
29
+ ['boolean', 'char', 'double', 'float', 'int', 'long'].each do |type_name|
30
+ type = AST::type(type_name)
31
+ return_type = @java_typer.method_type(@typer, string_meta, 'valueOf', [type])
32
+ assert_equal(string, return_type, "valueOf(#{type}) should return #{string}")
33
+ end
34
+
35
+ # char[]
36
+ type = AST::type('char', true)
37
+ return_type = @java_typer.method_type(@typer, string_meta, 'valueOf', [type])
38
+ assert_equal(string, return_type)
39
+
40
+ # Object
41
+ type = AST::type('java.lang.Object')
42
+ return_type = @java_typer.method_type(@typer, string_meta, 'valueOf', [type])
43
+ assert_equal(string, return_type)
44
+ end
45
+
46
+ def test_non_overtyped_method
47
+ string = AST::type('java.lang.String')
48
+
49
+ int = AST::type('int')
50
+ return_type = @java_typer.method_type(@typer, string, 'length', [])
51
+ assert_equal(int, return_type)
52
+
53
+ byte_array = AST::type('byte', true)
54
+ return_type = @java_typer.method_type(@typer, string, 'getBytes', [])
55
+ assert_equal(byte_array, return_type)
56
+ end
57
+
58
+ def test_simple_overtyped_method
59
+ string_meta = AST::type('java.lang.String', false, true)
60
+ string = AST::type('java.lang.String')
61
+
62
+ return_type = @java_typer.method_type(@typer, string_meta, 'valueOf', [string])
63
+ assert_equal(string, return_type)
64
+ end
65
+
66
+ def test_primitive_conversion_method
67
+ string = AST::type('java.lang.String')
68
+ byte = AST::type('byte')
69
+ char = AST::type('char')
70
+ long = AST::type('long')
71
+
72
+ return_type = @java_typer.method_type(@typer, string, 'charAt', [byte])
73
+ assert_equal(char, return_type)
74
+
75
+ assert_raise NoMethodError do
76
+ @java_typer.method_type(@typer, string, 'charAt', [long])
77
+ end
78
+ end
79
+
80
+ include Duby::JVM::MethodLookup
81
+
82
+ def test_complex_overtyped_method
83
+ printstream = java.io.PrintStream.java_class
84
+ object = java.lang.Object.java_class
85
+ string = java.lang.String.java_class
86
+
87
+ # best match is Object
88
+ method = find_method(printstream, "println", [object], false)
89
+ assert_match('println(java.lang.Object)', method.to_s)
90
+ # best match is String
91
+ method = find_method(printstream, "println", [string], false)
92
+ assert_match('println(java.lang.String)', method.to_s)
93
+ # only match is Object
94
+ method = find_method(printstream, "println", [printstream], false)
95
+ assert_match('println(java.lang.Object)', method.to_s)
96
+ end
97
+
98
+ def test_is_more_specific
99
+ object = java.lang.Object.java_class
100
+ charseq = java.lang.CharSequence.java_class
101
+ string = java.lang.String.java_class
102
+
103
+ assert @java_typer.is_more_specific?([string], [object])
104
+ assert @java_typer.is_more_specific?([charseq], [object])
105
+ assert @java_typer.is_more_specific?([string], [charseq])
106
+ end
107
+
108
+ def test_primitive_convertible
109
+ boolean = Java::boolean.java_class
110
+ byte = Java::byte.java_class
111
+ short = Java::short.java_class
112
+ char = Java::char.java_class
113
+ int = Java::int.java_class
114
+ long = Java::long.java_class
115
+ float = Java::float.java_class
116
+ double = Java::double.java_class
117
+
118
+ assert !primitive_convertible?(boolean, byte)
119
+ assert !primitive_convertible?(boolean, short)
120
+ assert !primitive_convertible?(boolean, char)
121
+ assert !primitive_convertible?(boolean, int)
122
+ assert !primitive_convertible?(boolean, long)
123
+ assert !primitive_convertible?(boolean, float)
124
+ assert !primitive_convertible?(boolean, double)
125
+ assert primitive_convertible?(boolean, boolean)
126
+
127
+ assert !primitive_convertible?(byte, boolean)
128
+ assert primitive_convertible?(byte, byte)
129
+ assert primitive_convertible?(byte, short)
130
+ assert primitive_convertible?(byte, char)
131
+ assert primitive_convertible?(byte, int)
132
+ assert primitive_convertible?(byte, long)
133
+ assert primitive_convertible?(byte, float)
134
+ assert primitive_convertible?(byte, double)
135
+
136
+ assert !primitive_convertible?(short, boolean)
137
+ assert !primitive_convertible?(short, byte)
138
+ assert !primitive_convertible?(short, char)
139
+ assert primitive_convertible?(short, short)
140
+ assert primitive_convertible?(short, int)
141
+ assert primitive_convertible?(short, long)
142
+ assert primitive_convertible?(short, float)
143
+ assert primitive_convertible?(short, double)
144
+
145
+ assert !primitive_convertible?(char, boolean)
146
+ assert !primitive_convertible?(char, byte)
147
+ assert !primitive_convertible?(char, short)
148
+ assert primitive_convertible?(char, char)
149
+ assert primitive_convertible?(char, int)
150
+ assert primitive_convertible?(char, long)
151
+ assert primitive_convertible?(char, float)
152
+ assert primitive_convertible?(char, double)
153
+
154
+ assert !primitive_convertible?(int, boolean)
155
+ assert !primitive_convertible?(int, byte)
156
+ assert !primitive_convertible?(int, short)
157
+ assert !primitive_convertible?(int, char)
158
+ assert primitive_convertible?(int, int)
159
+ assert primitive_convertible?(int, long)
160
+ assert primitive_convertible?(int, float)
161
+ assert primitive_convertible?(int, double)
162
+
163
+ assert !primitive_convertible?(long, boolean)
164
+ assert !primitive_convertible?(long, byte)
165
+ assert !primitive_convertible?(long, short)
166
+ assert !primitive_convertible?(long, char)
167
+ assert !primitive_convertible?(long, int)
168
+ assert primitive_convertible?(long, long)
169
+ assert !primitive_convertible?(long, float)
170
+ assert primitive_convertible?(long, double)
171
+
172
+ assert !primitive_convertible?(float, boolean)
173
+ assert !primitive_convertible?(float, byte)
174
+ assert !primitive_convertible?(float, short)
175
+ assert !primitive_convertible?(float, char)
176
+ assert !primitive_convertible?(float, int)
177
+ assert !primitive_convertible?(float, long)
178
+ assert primitive_convertible?(float, float)
179
+ assert primitive_convertible?(float, double)
180
+
181
+ assert !primitive_convertible?(double, boolean)
182
+ assert !primitive_convertible?(double, byte)
183
+ assert !primitive_convertible?(double, short)
184
+ assert !primitive_convertible?(double, char)
185
+ assert !primitive_convertible?(double, int)
186
+ assert !primitive_convertible?(double, long)
187
+ assert !primitive_convertible?(double, float)
188
+ assert primitive_convertible?(double, double)
189
+ end
190
+
191
+ def test_primitive_array
192
+ ary = AST.type('byte', true)
193
+ int = AST.type('int')
194
+
195
+ java_typer = Typer::JavaTyper.new
196
+
197
+ assert_equal(AST.type('byte'), java_typer.method_type(nil, ary, "[]", [int]))
198
+ end
199
+ end
@@ -0,0 +1,57 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
2
+
3
+ require 'test/unit'
4
+ require 'duby'
5
+ require 'duby/jvm/source_compiler'
6
+ require 'jruby'
7
+ require 'stringio'
8
+ require File.join(File.dirname(__FILE__), 'test_jvm_compiler')
9
+
10
+ class TestJavacCompiler < TestJVMCompiler
11
+ import javax.tools.ToolProvider
12
+ import java.util.Arrays
13
+ def javac(files)
14
+ compiler = ToolProvider.system_java_compiler
15
+ fm = compiler.get_standard_file_manager(nil, nil, nil)
16
+ units = fm.get_java_file_objects_from_strings(Arrays.as_list(files.to_java :string))
17
+ unless compiler.get_task(nil, fm, nil, nil, nil, units).call
18
+ raise "Compilation error"
19
+ end
20
+ loader = org.jruby.util.ClassCache::OneShotClassLoader.new(
21
+ JRuby.runtime.jruby_class_loader)
22
+ classes = []
23
+ files.each do |name|
24
+ classfile = name.sub /java$/, 'class'
25
+ if File.exist? classfile
26
+ bytecode = IO.read(classfile)
27
+ cls = loader.define_class(name[0..-6], bytecode.to_java_bytes)
28
+ classes << JavaUtilities.get_proxy_class(cls.name)
29
+ @tmp_classes << name
30
+ @tmp_classes << classfile
31
+ end
32
+ end
33
+ classes
34
+ end
35
+
36
+ def compile(code)
37
+ File.unlink(*@tmp_classes)
38
+ @tmp_classes.clear
39
+ AST.type_factory = Duby::JVM::Types::TypeFactory.new
40
+ ast = AST.parse(code)
41
+ name = "script" + System.nano_time.to_s
42
+ typer = Typer::JVM.new(name)
43
+ ast.infer(typer)
44
+ typer.resolve(true)
45
+ compiler = Compiler::JavaSource.new(name)
46
+ ast.compile(compiler, false)
47
+ java_files = []
48
+ compiler.generate do |name, builder|
49
+ bytes = builder.generate
50
+ open("#{name}", "w") do |f|
51
+ f << bytes
52
+ end
53
+ java_files << name
54
+ end
55
+ classes = javac(java_files)
56
+ end
57
+ end
@@ -0,0 +1,1459 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
2
+
3
+ require 'test/unit'
4
+ require 'duby'
5
+ require 'jruby'
6
+ require 'stringio'
7
+
8
+ class TestJVMCompiler < Test::Unit::TestCase
9
+ include Duby
10
+ import java.lang.System
11
+ import java.io.PrintStream
12
+
13
+ def setup
14
+ @tmp_classes = []
15
+ end
16
+
17
+ def teardown
18
+ AST.type_factory = nil
19
+ File.unlink(*@tmp_classes)
20
+ end
21
+
22
+ def assert_include(value, array, message=nil)
23
+ message = build_message message, '<?> does not include <?>', array, value
24
+ assert_block message do
25
+ array.include? value
26
+ end
27
+ end
28
+
29
+ def compile(code)
30
+ File.unlink(*@tmp_classes)
31
+ @tmp_classes.clear
32
+ AST.type_factory = Duby::JVM::Types::TypeFactory.new
33
+ name = "script" + System.nano_time.to_s
34
+ ast = AST.parse(code, name, true)
35
+ typer = Typer::JVM.new(name)
36
+ ast.infer(typer)
37
+ typer.resolve(true)
38
+ compiler = Compiler::JVM.new(name)
39
+ compiler.compile(ast)
40
+ classes = []
41
+ loader = org.jruby.util.ClassCache::OneShotClassLoader.new(
42
+ JRuby.runtime.jruby_class_loader)
43
+ compiler.generate do |name, builder|
44
+ bytes = builder.generate
45
+ open("#{name}", "w") do |f|
46
+ f << bytes
47
+ end
48
+ cls = loader.define_class(name[0..-7], bytes.to_java_bytes)
49
+ classes << JavaUtilities.get_proxy_class(cls.name)
50
+ @tmp_classes << "#{name}"
51
+ end
52
+
53
+ classes
54
+ end
55
+
56
+ def test_local
57
+ cls, = compile("def foo; a = 1; a; end")
58
+ assert_equal(1, cls.foo)
59
+
60
+ cls, = compile("def foo; a = 1.0; a; end")
61
+ assert_equal(1.0, cls.foo)
62
+
63
+ cls, = compile("def foo; a = 'bar'; a; end")
64
+ assert_equal('bar', cls.foo)
65
+ end
66
+
67
+ def test_addition
68
+ cls, = compile("def foo; a = 1; b = 2; a + b; end")
69
+ assert_equal(3, cls.foo)
70
+
71
+ cls, = compile("def foo; a = 1.0; b = 2.0; a + b; end")
72
+ assert_equal(3.0, cls.foo)
73
+ end
74
+
75
+ def test_subtraction
76
+ cls, = compile("def foo; a = 3; b = 2; a - b; end")
77
+ assert_equal(1, cls.foo)
78
+
79
+ cls, = compile("def foo; a = 3.0; b = 2.0; a - b; end")
80
+ assert_equal(1.0, cls.foo)
81
+ end
82
+
83
+ def test_multiplication
84
+ cls, = compile("def foo; a = 2; b = 3; a * b; end")
85
+ assert_equal(6, cls.foo)
86
+
87
+ cls, = compile("def foo; a = 2.0; b = 3.0; a * b; end")
88
+ assert_equal(6.0, cls.foo)
89
+ end
90
+
91
+ def test_division
92
+ cls, = compile("def foo; a = 6; b = 3; a / b; end")
93
+ assert_equal(2, cls.foo)
94
+
95
+ cls, = compile("def foo; a = 6.0; b = 3.0; a / b; end")
96
+ assert_equal(2.0, cls.foo)
97
+ end
98
+
99
+ def test_rem
100
+ cls, = compile("def foo; a = 7; b = 3; a % b; end")
101
+ assert_equal(1, cls.foo)
102
+
103
+ cls, = compile("def foo; a = 8.0; b = 3.0; a % b; end")
104
+ assert_equal(2.0, cls.foo)
105
+ end
106
+
107
+ def test_shift_left
108
+ cls, = compile("def foo; a = 1; b = 3; a << b; end")
109
+ assert_equal(8, cls.foo)
110
+ end
111
+
112
+ def test_shift_right
113
+ cls, = compile("def foo; a = 7; b = 2; a >> b; end")
114
+ assert_equal(1, cls.foo)
115
+
116
+ cls, = compile("def foo; a = -1; b = 1; a >> b; end")
117
+ assert_equal(-1, cls.foo)
118
+ end
119
+
120
+ # TODO the parser doesn't like >>>
121
+
122
+ # def test_unsigned_shift_right
123
+ # cls, = compile("def foo; a = -1; b = 31; a >>> b; end")
124
+ # assert_equal(1, cls.foo)
125
+ # end
126
+
127
+ def test_binary_and
128
+ cls, = compile("def foo; a = 7; b = 3; a & b; end")
129
+ assert_equal(3, cls.foo)
130
+ end
131
+
132
+ def test_binary_or
133
+ cls, = compile("def foo; a = 4; b = 3; a | b; end")
134
+ assert_equal(7, cls.foo)
135
+ end
136
+
137
+ def test_binary_xor
138
+ cls, = compile("def foo; a = 5; b = 3; a ^ b; end")
139
+ assert_equal(6, cls.foo)
140
+ end
141
+
142
+ def test_return
143
+ cls, = compile("def foo; return 1; end")
144
+ assert_equal(1, cls.foo)
145
+
146
+ cls, = compile("def foo; return 1.0; end")
147
+ assert_equal(1.0, cls.foo)
148
+
149
+ cls, = compile("def foo; return 'bar'; end")
150
+ assert_equal('bar', cls.foo)
151
+ end
152
+
153
+ def test_primitive_array
154
+ cls, = compile("def foo; a = boolean[2]; a; end")
155
+ assert_equal(Java::boolean[].java_class, cls.foo.class.java_class)
156
+ assert_equal([false,false], cls.foo.to_a)
157
+ cls, = compile("def foo; a = boolean[2]; a[0] = true; a[0]; end")
158
+ assert_equal(TrueClass, cls.foo.class)
159
+ assert_equal(true, cls.foo)
160
+ cls, = compile("def foo; a = boolean[2]; a.length; end")
161
+ assert_equal(Fixnum, cls.foo.class)
162
+ assert_equal(2, cls.foo)
163
+
164
+ cls, = compile("def foo; a = byte[2]; a; end")
165
+ assert_equal(Java::byte[].java_class, cls.foo.class.java_class)
166
+ assert_equal([0,0], cls.foo.to_a)
167
+ cls, = compile("def foo; a = byte[2]; a[0] = 1; a[0]; end")
168
+ assert_equal(Fixnum, cls.foo.class)
169
+ assert_equal(1, cls.foo)
170
+
171
+ cls, = compile("def foo; a = short[2]; a; end")
172
+ assert_equal(Java::short[].java_class, cls.foo.class.java_class)
173
+ assert_equal([0,0], cls.foo.to_a)
174
+ cls, = compile("def foo; a = short[2]; a[0] = 1; a[0]; end")
175
+ assert_equal(Fixnum, cls.foo.class)
176
+ assert_equal(1, cls.foo)
177
+
178
+ cls, = compile("def foo; a = char[2]; a; end")
179
+ assert_equal(Java::char[].java_class, cls.foo.class.java_class)
180
+ assert_equal([0,0], cls.foo.to_a)
181
+ # Pending char constants or casts
182
+ # cls, = compile("def foo; a = char[2]; a[0] = 1; a[0]; end")
183
+ # assert_equal(Fixnum, cls.foo.class)
184
+ # assert_equal(1, cls.foo)
185
+
186
+ cls, = compile("def foo; a = int[2]; a; end")
187
+ assert_equal(Java::int[].java_class, cls.foo.class.java_class)
188
+ assert_equal([0,0], cls.foo.to_a)
189
+ cls, = compile("def foo; a = int[2]; a[0] = 1; a[0]; end")
190
+ assert_equal(Fixnum, cls.foo.class)
191
+ assert_equal(1, cls.foo)
192
+
193
+ cls, = compile("def foo; a = long[2]; a; end")
194
+ assert_equal(Java::long[].java_class, cls.foo.class.java_class)
195
+ assert_equal([0,0], cls.foo.to_a)
196
+ cls, = compile(<<-EOF)
197
+ def foo
198
+ a = long[2]
199
+ a[0] = 1
200
+ a[0]
201
+ end
202
+ EOF
203
+ assert_equal(Fixnum, cls.foo.class)
204
+ assert_equal(1, cls.foo)
205
+
206
+ cls, = compile("def foo; a = float[2]; a; end")
207
+ assert_equal(Java::float[].java_class, cls.foo.class.java_class)
208
+ assert_equal([0.0,0.0], cls.foo.to_a)
209
+ cls, = compile("def foo; a = float[2]; a[0] = 1.0; a[0]; end")
210
+ assert_equal(Float, cls.foo.class)
211
+ assert_equal(1.0, cls.foo)
212
+
213
+ cls, = compile("def foo; a = double[2]; a; end")
214
+ assert_equal(Java::double[].java_class, cls.foo.class.java_class)
215
+ assert_equal([0.0,0.0], cls.foo.to_a)
216
+ cls, = compile(<<-EOF)
217
+ def foo
218
+ a = double[2]
219
+ # awaiting implicit F2D
220
+ # a[0] = 1.0
221
+ a[0]
222
+ end
223
+ EOF
224
+ assert_equal(Float, cls.foo.class)
225
+ assert_equal(0.0, cls.foo)
226
+ end
227
+
228
+ def test_array_with_dynamic_size
229
+ cls, = compile("def foo(size => :int); a = int[size + 1];end")
230
+ array = cls.foo(3)
231
+ assert_equal(Java::int[].java_class, array.class.java_class)
232
+ assert_equal([0,0,0,0], array.to_a)
233
+ end
234
+
235
+ def test_object_array
236
+ cls, = compile("import java.lang.Object;def foo; a = Object[2];end")
237
+ assert_equal(Java::JavaLang::Object[].java_class, cls.foo.class.java_class)
238
+ assert_equal([nil, nil], cls.foo.to_a)
239
+ end
240
+
241
+ def test_string_concat
242
+ cls, = compile("def foo; a = 'a'; b = 'b'; a + b; end")
243
+ assert_equal("ab", cls.foo)
244
+ end
245
+
246
+ def test_void_selfcall
247
+ cls, = compile("import 'System', 'java.lang.System'; def foo; System.gc; end; foo")
248
+ assert_nothing_raised {cls.foo}
249
+ end
250
+
251
+ def test_import
252
+ cls, = compile("import 'AL', 'java.util.ArrayList'; def foo; AL.new; end; foo")
253
+ assert_equal java.util.ArrayList.java_class, cls.foo.java_class
254
+
255
+ cls, = compile("import 'java.util.ArrayList'; def foo; ArrayList.new; end; foo")
256
+ assert_equal java.util.ArrayList.java_class, cls.foo.java_class
257
+ end
258
+
259
+ def test_no_quote_import
260
+ cls, = compile("import java.util.ArrayList as AL; def foo; AL.new; end; foo")
261
+ assert_equal java.util.ArrayList.java_class, cls.foo.java_class
262
+
263
+ cls, = compile("import java.util.ArrayList; def foo; ArrayList.new; end; foo")
264
+ assert_equal java.util.ArrayList.java_class, cls.foo.java_class
265
+ end
266
+
267
+ def test_imported_decl
268
+ cls, = compile("import 'java.util.ArrayList'; def foo(a => ArrayList); a.size; end")
269
+ assert_equal 0, cls.foo(java.util.ArrayList.new)
270
+ end
271
+
272
+ def test_interface
273
+ cls, = compile(<<-EOF)
274
+ import 'java.util.concurrent.Callable'
275
+ def foo(a => Callable)
276
+ throws Exception
277
+ a.call
278
+ end
279
+ EOF
280
+ result = cls.foo {0}
281
+ assert_equal 0, result
282
+ m = cls.java_class.java_method 'foo', java.util.concurrent.Callable
283
+ assert_equal([java.lang.Exception.java_class], m.exception_types)
284
+
285
+ end
286
+
287
+ def test_class_decl
288
+ script, foo = compile("class ClassDeclTest;end")
289
+ assert_equal('ClassDeclTest', foo.java_class.name)
290
+ end
291
+
292
+ def capture_output
293
+ saved_output = System.out
294
+ output = StringIO.new
295
+ System.setOut(PrintStream.new(output.to_outputstream))
296
+ begin
297
+ yield
298
+ output.rewind
299
+ output.read
300
+ ensure
301
+ System.setOut(saved_output)
302
+ end
303
+ end
304
+
305
+ def assert_output(expected, &block)
306
+ assert_equal(expected, capture_output(&block))
307
+ end
308
+
309
+ def test_puts
310
+ cls, = compile("def foo;puts 'Hello World!';end")
311
+ output = capture_output do
312
+ cls.foo
313
+ end
314
+ assert_equal("Hello World!\n", output)
315
+ end
316
+
317
+ def test_constructor
318
+ script, cls = compile(
319
+ "class InitializeTest;def initialize;puts 'Constructed';end;end")
320
+ output = capture_output do
321
+ cls.new
322
+ end
323
+ assert_equal("Constructed\n", output)
324
+ end
325
+
326
+ def test_method
327
+ # TODO auto generate a constructor
328
+ script, cls = compile(
329
+ "class MethodTest; def initialize; ''; end; def foo; 'foo';end;end")
330
+ instance = cls.new
331
+ assert_equal(cls, instance.class)
332
+ assert_equal('foo', instance.foo)
333
+ end
334
+
335
+ def test_unless_fixnum
336
+ cls, = compile(<<-EOF)
337
+ def foo(a => :fixnum)
338
+ values = boolean[5]
339
+ values[0] = true unless a < 0
340
+ values[1] = true unless a <= 0
341
+ values[2] = true unless a == 0
342
+ values[3] = true unless a >= 0
343
+ values[4] = true unless a > 0
344
+ values
345
+ end
346
+ EOF
347
+ assert_equal [true, true, true, false, false], cls.foo(1).to_a
348
+ assert_equal [true, false, false, false, true], cls.foo(0).to_a
349
+ assert_equal [false, false, true, true, true], cls.foo(-1).to_a
350
+ end
351
+
352
+ def test_unless_float
353
+ cls, = compile(<<-EOF)
354
+ def foo(a => :float)
355
+ values = boolean[5]
356
+ values[0] = true unless a < 0.0
357
+ values[1] = true unless a <= 0.0
358
+ values[2] = true unless a == 0.0
359
+ values[3] = true unless a >= 0.0
360
+ values[4] = true unless a > 0.0
361
+ values
362
+ end
363
+ EOF
364
+ assert_equal [true, true, true, false, false], cls.foo(1.0).to_a
365
+ assert_equal [true, false, false, false, true], cls.foo(0.0).to_a
366
+ assert_equal [false, false, true, true, true], cls.foo(-1.0).to_a
367
+ end
368
+
369
+ def test_if_fixnum
370
+ cls, = compile(<<-EOF)
371
+ def foo(a => :fixnum)
372
+ if a < -5
373
+ -6
374
+ elsif a <= 0
375
+ 0
376
+ elsif a == 1
377
+ 1
378
+ elsif a > 4
379
+ 5
380
+ elsif a >= 3
381
+ 3
382
+ else
383
+ 2
384
+ end
385
+ end
386
+ EOF
387
+ assert_equal(-6, cls.foo(-6))
388
+ assert_equal(0, cls.foo(-5))
389
+ assert_equal(0, cls.foo(0))
390
+ assert_equal(1, cls.foo(1))
391
+ assert_equal(2, cls.foo(2))
392
+ assert_equal(3, cls.foo(3))
393
+ assert_equal(3, cls.foo(4))
394
+ assert_equal(5, cls.foo(5))
395
+ end
396
+
397
+ def test_if_float
398
+ cls, = compile(<<-EOF)
399
+ def foo(a => :float)
400
+ if a < -5.0
401
+ -6
402
+ elsif a <= 0.0
403
+ 0
404
+ elsif a == 1.0
405
+ 1
406
+ elsif a > 4.0
407
+ 5
408
+ elsif a >= 3.0
409
+ 3
410
+ else
411
+ 2
412
+ end
413
+ end
414
+ EOF
415
+ assert_equal(-6, cls.foo(-5.1))
416
+ assert_equal(0, cls.foo(-5.0))
417
+ assert_equal(0, cls.foo(0.0))
418
+ assert_equal(1, cls.foo(1.0))
419
+ assert_equal(2, cls.foo(2.5))
420
+ assert_equal(3, cls.foo(3.0))
421
+ assert_equal(3, cls.foo(3.5))
422
+ assert_equal(5, cls.foo(4.1))
423
+ end
424
+
425
+ def test_if_boolean
426
+ cls, = compile(<<-EOF)
427
+ def foo(a => :boolean)
428
+ if a
429
+ 'true'
430
+ else
431
+ 'false'
432
+ end
433
+ end
434
+ EOF
435
+ assert_equal('true', cls.foo(true))
436
+ assert_equal('false', cls.foo(false))
437
+ end
438
+
439
+ def test_if_int
440
+ # conditions don't work with :int
441
+ # cls, = compile("def foo(a => :int); if a < 0; -a; else; a; end; end")
442
+ # assert_equal 1, cls.foo(-1)
443
+ # assert_equal 3, cls.foo(3)
444
+ end
445
+
446
+ def test_trailing_conditions
447
+ cls, = compile(<<-EOF)
448
+ def foo(a => :fixnum)
449
+ return '+' if a > 0
450
+ return '0' unless a < 0
451
+ '-'
452
+ end
453
+ EOF
454
+ assert_equal '+', cls.foo(3)
455
+ assert_equal '0', cls.foo(0)
456
+ assert_equal '-', cls.foo(-1)
457
+ end
458
+
459
+
460
+ def test_local_decl
461
+ cls, = compile(<<-EOF)
462
+ import 'java.lang.String'
463
+ a = :fixnum
464
+ b = :int
465
+ c = :long
466
+ d = :float
467
+ e = :string
468
+ f = String
469
+ puts a
470
+ puts b
471
+ puts c
472
+ puts d
473
+ puts e
474
+ puts f
475
+ EOF
476
+ output = capture_output do
477
+ cls.main([].to_java(:string))
478
+ end
479
+ assert_equal("0\n0\n0\n0.0\nnull\nnull\n", output)
480
+ end
481
+
482
+ def test_multi_assign
483
+ cls, = compile(<<-EOF)
484
+ def foo
485
+ array = int[2]
486
+ a = b = 2
487
+ array[0] = a
488
+ array[1] = b
489
+ array
490
+ end
491
+ EOF
492
+ assert_equal([2, 2], cls.foo.to_a)
493
+
494
+ end
495
+
496
+ def test_loop
497
+ cls, = compile(
498
+ 'def foo(a => :fixnum);while a > 0; a -= 1; puts ".";end;end')
499
+ assert_equal('', capture_output{cls.foo(0)})
500
+ assert_equal(".\n", capture_output{cls.foo(1)})
501
+ assert_equal(".\n.\n", capture_output{cls.foo(2)})
502
+
503
+ cls, = compile(
504
+ 'def foo(a => :fixnum);begin;a -= 1; puts ".";end while a > 0;end')
505
+ assert_equal(".\n", capture_output{cls.foo(0)})
506
+ assert_equal(".\n", capture_output{cls.foo(1)})
507
+ assert_equal(".\n.\n", capture_output{cls.foo(2)})
508
+
509
+ cls, = compile(
510
+ 'def foo(a => :fixnum);until a <= 0; a -= 1; puts ".";end;end')
511
+ assert_equal('', capture_output{cls.foo(0)})
512
+ assert_equal(".\n", capture_output{cls.foo(1)})
513
+ assert_equal(".\n.\n", capture_output{cls.foo(2)})
514
+
515
+ cls, = compile(
516
+ 'def foo(a => :fixnum);begin;a -= 1; puts ".";end until a <= 0;end')
517
+ assert_equal(".\n", capture_output{cls.foo(0)})
518
+ assert_equal(".\n", capture_output{cls.foo(1)})
519
+ assert_equal(".\n.\n", capture_output{cls.foo(2)})
520
+
521
+ cls, = compile(
522
+ 'def foo; a = 0; while a < 2; a+=1; end; end')
523
+ assert_equal(nil, cls.foo)
524
+ end
525
+
526
+ def test_break
527
+ cls, = compile <<-EOF
528
+ def foo
529
+ count = 0
530
+ while count < 5
531
+ count += 1
532
+ break if count == 1
533
+ end
534
+ count
535
+ end
536
+ EOF
537
+ assert_equal(1, cls.foo)
538
+
539
+ cls, = compile <<-EOF
540
+ def foo
541
+ a = 0
542
+ b = 0
543
+ while a < 2
544
+ a += 1
545
+ while b < 5
546
+ b += 1
547
+ break if b > 0
548
+ end
549
+ break if a == 1
550
+ end
551
+ a * 100 + b
552
+ end
553
+ EOF
554
+ assert_equal(101, cls.foo)
555
+
556
+ cls, = compile <<-EOF
557
+ def foo
558
+ count = 0
559
+ begin
560
+ count += 1
561
+ break if count == 1
562
+ end while count < 5
563
+ count
564
+ end
565
+ EOF
566
+ assert_equal(1, cls.foo)
567
+ end
568
+
569
+ def test_next
570
+ cls, = compile <<-EOF
571
+ def foo
572
+ values = int[3]
573
+ i = 0
574
+ while i < 3
575
+ i += 1
576
+ next if i == 2
577
+ values[i - 1] = i
578
+ end
579
+ values
580
+ end
581
+ EOF
582
+ assert_equal([1, 0, 3], cls.foo.to_a)
583
+
584
+ cls, = compile <<-EOF
585
+ def foo
586
+ i = 0
587
+ while i < 5
588
+ i += 1
589
+ next if i == 5
590
+ end
591
+ i
592
+ end
593
+ EOF
594
+ assert_equal(5, cls.foo)
595
+
596
+ cls, = compile <<-EOF
597
+ def foo
598
+ values = int[3]
599
+ a = 0
600
+ b = 0
601
+ while a < 3
602
+ b = 0
603
+ while b < 5
604
+ b += 1
605
+ next if b == a + 1
606
+ # values[a] += b # TODO
607
+ values[a] = values[a] + b
608
+ end
609
+ a += 1
610
+ next if a == 2
611
+ values[a - 1] = values[a - 1] + a * 100
612
+ end
613
+ values
614
+ end
615
+ EOF
616
+ assert_equal([114, 13, 312], cls.foo.to_a)
617
+
618
+ cls, = compile <<-EOF
619
+ def foo
620
+ count = 0
621
+ sum = 0
622
+ begin
623
+ count += 1
624
+ next if count == 2
625
+ sum += count
626
+ next if count == 5
627
+ end while count < 5
628
+ count * 100 + sum
629
+ end
630
+ EOF
631
+ assert_equal(513, cls.foo)
632
+ end
633
+
634
+ def test_redo
635
+ cls, = compile <<-EOF
636
+ def foo
637
+ i = 0
638
+ while i < 5
639
+ i += 1
640
+ redo if i == 5
641
+ end
642
+ i
643
+ end
644
+ EOF
645
+ assert_equal(6, cls.foo)
646
+
647
+ cls, = compile <<-EOF
648
+ def foo
649
+ values = int[4]
650
+ a = 0
651
+ b = 0
652
+ while a < 3
653
+ b = a
654
+ while b < 5
655
+ b += 1
656
+ redo if b == 5
657
+ values[a] = values[a] + b
658
+ end
659
+ a += 1
660
+ values[a - 1] = values[a - 1] + a * 100
661
+ redo if a == 3
662
+ end
663
+ values
664
+ end
665
+ EOF
666
+ assert_equal([116, 215, 313, 410], cls.foo.to_a)
667
+
668
+ cls, = compile <<-EOF
669
+ def foo
670
+ i = 0
671
+ begin
672
+ i += 1
673
+ redo if i == 5
674
+ end while i < 5
675
+ i
676
+ end
677
+ EOF
678
+ assert_equal(6, cls.foo)
679
+ end
680
+
681
+ def test_fields
682
+ script, cls = compile(<<-EOF)
683
+ class FieldTest
684
+ def initialize(a => :fixnum)
685
+ @a = a
686
+ end
687
+
688
+ def a
689
+ @a
690
+ end
691
+ end
692
+ EOF
693
+ first = cls.new(1)
694
+ assert_equal(1, first.a)
695
+
696
+ second = cls.new(2)
697
+ assert_equal(1, first.a)
698
+ assert_equal(2, second.a)
699
+ end
700
+
701
+ def test_object_intrinsics
702
+ cls, = compile(<<-EOF)
703
+ import 'java.lang.Object'
704
+ def nil(a => :Object)
705
+ a.nil?
706
+ end
707
+
708
+ def equal(a => Object, b => Object)
709
+ a == b
710
+ end
711
+ EOF
712
+
713
+ assert(cls.nil(nil))
714
+ assert(!cls.nil("abc"))
715
+
716
+ a = "foobar".to_java_string
717
+ b = java.lang.Object.new
718
+ assert(cls.equal(a, a))
719
+ assert(cls.equal(b, b))
720
+ assert(!cls.equal(a, b))
721
+ end
722
+
723
+ def test_implements
724
+ script, cls = compile(<<-EOF)
725
+ import java.lang.Iterable
726
+ class Foo; implements Iterable
727
+ def iterator
728
+ nil
729
+ end
730
+ end
731
+ EOF
732
+
733
+ assert_include java.lang.Iterable.java_class, cls.java_class.interfaces
734
+ end
735
+
736
+ def test_argument_widening
737
+ cls, = compile(<<-EOF)
738
+ def Byte(a => :byte)
739
+ Short(a)
740
+ end
741
+
742
+ def Short(a => :short)
743
+ Int(a)
744
+ end
745
+
746
+ def Int(a => :int)
747
+ Long(a)
748
+ end
749
+
750
+ def Long(a => :long)
751
+ Float(a)
752
+ end
753
+
754
+ def Float(a => :float)
755
+ Double(a)
756
+ end
757
+
758
+ def Double(a => :double)
759
+ a
760
+ end
761
+ EOF
762
+
763
+ assert_equal(1.0, cls.Byte(1))
764
+ assert_equal(127.0, cls.Byte(127))
765
+ assert_equal(128.0, cls.Short(128))
766
+ assert_equal(32767.0, cls.Short(32767))
767
+ assert_equal(32768.0, cls.Int(32768))
768
+ assert_equal(2147483648.0, cls.Long(2147483648))
769
+ end
770
+
771
+ def test_interface_declaration
772
+ script, interface = compile('interface A do; end')
773
+ assert(interface.java_class.interface?)
774
+ assert_equal('A', interface.java_class.name)
775
+
776
+ script, a, b = compile('interface A do; end; interface B < A do; end')
777
+ assert_include(a, b.ancestors)
778
+ assert_equal('A', a.java_class.name)
779
+ assert_equal('B', b.java_class.name)
780
+
781
+ script, a, b, c = compile(<<-EOF)
782
+ interface A do
783
+ end
784
+
785
+ interface B do
786
+ end
787
+
788
+ interface C < A, B do
789
+ end
790
+ EOF
791
+
792
+ assert_include(a, c.ancestors)
793
+ assert_include(b, c.ancestors)
794
+ assert_equal('A', a.java_class.name)
795
+ assert_equal('B', b.java_class.name)
796
+ assert_equal('C', c.java_class.name)
797
+
798
+ assert_raise Duby::Typer::InferenceError do
799
+ compile(<<-EOF)
800
+ interface A do
801
+ def a
802
+ returns :int
803
+ end
804
+ end
805
+
806
+ class Impl; implements A
807
+ def a
808
+ "foo"
809
+ end
810
+ end
811
+ EOF
812
+ end
813
+ end
814
+
815
+ def assert_throw(type, message=nil)
816
+ ex = assert_raise(NativeException) do
817
+ yield
818
+ end
819
+ assert_equal type, ex.cause.class
820
+ assert_equal message, ex.cause.message
821
+ end
822
+
823
+ def test_raise
824
+ cls, = compile(<<-EOF)
825
+ def foo
826
+ raise
827
+ end
828
+ EOF
829
+ assert_throw(java.lang.RuntimeException) do
830
+ cls.foo
831
+ end
832
+
833
+ cls, = compile(<<-EOF)
834
+ def foo
835
+ raise "Oh no!"
836
+ end
837
+ EOF
838
+ ex = assert_throw(java.lang.RuntimeException, 'Oh no!') do
839
+ cls.foo
840
+ end
841
+
842
+ cls, = compile(<<-EOF)
843
+ def foo
844
+ raise IllegalArgumentException
845
+ end
846
+ EOF
847
+ ex = assert_throw(java.lang.IllegalArgumentException) do
848
+ cls.foo
849
+ end
850
+
851
+ cls, = compile(<<-EOF)
852
+ def foo
853
+ throws Exception
854
+ raise Exception, "oops"
855
+ end
856
+ EOF
857
+ ex = assert_throw(java.lang.Exception, "oops") do
858
+ cls.foo
859
+ end
860
+
861
+ cls, = compile(<<-EOF)
862
+ def foo
863
+ throws Throwable
864
+ raise Throwable.new("darn")
865
+ end
866
+ EOF
867
+ ex = assert_throw(java.lang.Throwable, "darn") do
868
+ cls.foo
869
+ end
870
+ end
871
+
872
+ def test_rescue
873
+ cls, = compile(<<-EOF)
874
+ def foo
875
+ begin
876
+ puts "body"
877
+ rescue
878
+ puts "rescue"
879
+ end
880
+ end
881
+ EOF
882
+
883
+ output = capture_output do
884
+ cls.foo
885
+ end
886
+ assert_equal("body\n", output)
887
+
888
+ cls, = compile(<<-EOF)
889
+ def foo
890
+ begin
891
+ puts "body"
892
+ raise
893
+ rescue
894
+ puts "rescue"
895
+ end
896
+ end
897
+ EOF
898
+
899
+ output = capture_output do
900
+ cls.foo
901
+ end
902
+ assert_equal("body\nrescue\n", output)
903
+
904
+ cls, = compile(<<-EOF)
905
+ def foo(a:int)
906
+ begin
907
+ puts "body"
908
+ if a == 0
909
+ raise IllegalArgumentException
910
+ else
911
+ raise
912
+ end
913
+ rescue IllegalArgumentException
914
+ puts "IllegalArgumentException"
915
+ rescue
916
+ puts "rescue"
917
+ end
918
+ end
919
+ EOF
920
+
921
+ output = capture_output do
922
+ cls.foo(1)
923
+ cls.foo(0)
924
+ end
925
+ assert_equal("body\nrescue\nbody\nIllegalArgumentException\n", output)
926
+
927
+ cls, = compile(<<-EOF)
928
+ def foo(a:int)
929
+ begin
930
+ puts "body"
931
+ if a == 0
932
+ raise IllegalArgumentException
933
+ elsif a == 1
934
+ raise Throwable
935
+ else
936
+ raise
937
+ end
938
+ rescue IllegalArgumentException, RuntimeException
939
+ puts "multi"
940
+ rescue Throwable
941
+ puts "other"
942
+ end
943
+ end
944
+ EOF
945
+
946
+ output = capture_output do
947
+ cls.foo(0)
948
+ cls.foo(1)
949
+ cls.foo(2)
950
+ end
951
+ assert_equal("body\nmulti\nbody\nother\nbody\nmulti\n", output)
952
+
953
+ cls, = compile(<<-EOF)
954
+ def foo
955
+ begin
956
+ raise "foo"
957
+ rescue => ex
958
+ puts ex.getMessage
959
+ end
960
+ end
961
+ EOF
962
+
963
+ output = capture_output do
964
+ cls.foo
965
+ end
966
+ assert_equal("foo\n", output)
967
+ end
968
+
969
+ def test_ensure
970
+ cls, = compile(<<-EOF)
971
+ def foo
972
+ 1
973
+ ensure
974
+ puts "Hi"
975
+ end
976
+ EOF
977
+ output = capture_output do
978
+ assert_equal(1, cls.foo)
979
+ end
980
+ assert_equal "Hi\n", output
981
+
982
+ cls, = compile(<<-EOF)
983
+ def foo
984
+ return 1
985
+ ensure
986
+ puts "Hi"
987
+ end
988
+ EOF
989
+ output = capture_output do
990
+ assert_equal(1, cls.foo)
991
+ end
992
+ assert_equal "Hi\n", output
993
+
994
+ cls, = compile(<<-EOF)
995
+ def foo
996
+ begin
997
+ break
998
+ ensure
999
+ puts "Hi"
1000
+ end while false
1001
+ end
1002
+ EOF
1003
+ output = capture_output do
1004
+ cls.foo
1005
+ end
1006
+ assert_equal "Hi\n", output
1007
+
1008
+ end
1009
+
1010
+ def test_cast
1011
+ cls, = compile(<<-EOF)
1012
+ def f2b; byte(1.0); end
1013
+ def f2s; short(1.0); end
1014
+ def f2c; char(1.0); end
1015
+ def f2i; int(1.0); end
1016
+ def f2l; long(1.0); end
1017
+ def f2d; int(1.0); end
1018
+
1019
+ def i2b; byte(1); end
1020
+ def i2s; short(1); end
1021
+ def i2c; char(1); end
1022
+ def i2l; long(1); end
1023
+ def i2f; float(1); end
1024
+ def i2d; int(1); end
1025
+
1026
+ def b2s; short(byte(1)); end
1027
+ def b2c; char(byte(1)); end
1028
+ def b2i; int(byte(1)); end
1029
+ def b2l; long(byte(1)); end
1030
+ def b2f; float(byte(1)); end
1031
+ def b2d; double(byte(1)); end
1032
+
1033
+ def s2b; byte(short(1)); end
1034
+ def s2c; char(short(1)); end
1035
+ def s2i; int(short(1)); end
1036
+ def s2l; long(short(1)); end
1037
+ def s2f; float(short(1)); end
1038
+ def s2d; double(short(1)); end
1039
+
1040
+ def c2b; byte(char(1)); end
1041
+ def c2s; short(char(1)); end
1042
+ def c2i; int(char(1)); end
1043
+ def c2l; long(char(1)); end
1044
+ def c2f; float(char(1)); end
1045
+ def c2d; double(char(1)); end
1046
+
1047
+ def l2b; byte(long(1)); end
1048
+ def l2c; char(long(1)); end
1049
+ def l2i; int(long(1)); end
1050
+ def l2l; long(long(1)); end
1051
+ def l2f; float(long(1)); end
1052
+ def l2d; double(long(1)); end
1053
+
1054
+ def d2b; byte(1.0); end
1055
+ def d2s; short(1.0); end
1056
+ def d2c; char(1.0); end
1057
+ def d2i; int(1.0); end
1058
+ def d2l; long(1.0); end
1059
+ def d2f; float(1.0); end
1060
+
1061
+ def hard_i2f(a:int)
1062
+ float(if a < 0
1063
+ a *= -1
1064
+ a * 2
1065
+ else
1066
+ a * 2
1067
+ end)
1068
+ end
1069
+ EOF
1070
+
1071
+ assert_equal 1, cls.b2s
1072
+ assert_equal 1, cls.b2c
1073
+ assert_equal 1, cls.b2i
1074
+ assert_equal 1, cls.b2l
1075
+ assert_equal 1.0, cls.b2f
1076
+ assert_equal 1.0, cls.b2d
1077
+
1078
+ assert_equal 1, cls.s2b
1079
+ assert_equal 1, cls.s2c
1080
+ assert_equal 1, cls.s2i
1081
+ assert_equal 1, cls.s2l
1082
+ assert_equal 1.0, cls.s2f
1083
+ assert_equal 1.0, cls.s2d
1084
+
1085
+ assert_equal 1, cls.c2b
1086
+ assert_equal 1, cls.c2s
1087
+ assert_equal 1, cls.c2i
1088
+ assert_equal 1, cls.c2l
1089
+ assert_equal 1.0, cls.c2f
1090
+ assert_equal 1.0, cls.c2d
1091
+
1092
+ assert_equal 1, cls.i2b
1093
+ assert_equal 1, cls.i2s
1094
+ assert_equal 1, cls.i2c
1095
+ assert_equal 1, cls.i2l
1096
+ assert_equal 1.0, cls.i2f
1097
+ assert_equal 1.0, cls.i2d
1098
+
1099
+ assert_equal 1, cls.f2b
1100
+ assert_equal 1, cls.f2s
1101
+ assert_equal 1, cls.f2c
1102
+ assert_equal 1, cls.f2i
1103
+ assert_equal 1, cls.f2l
1104
+ assert_equal 1.0, cls.f2d
1105
+
1106
+ assert_equal 1, cls.d2b
1107
+ assert_equal 1, cls.d2s
1108
+ assert_equal 1, cls.d2c
1109
+ assert_equal 1, cls.d2i
1110
+ assert_equal 1, cls.d2l
1111
+ assert_equal 1.0, cls.d2f
1112
+
1113
+ assert_equal 2.0, cls.hard_i2f(1)
1114
+ assert_equal 4.0, cls.hard_i2f(-2)
1115
+ end
1116
+
1117
+ def test_set
1118
+ cls, = compile(<<-EOF)
1119
+ def foo
1120
+ @foo
1121
+ end
1122
+
1123
+ def foo=(foo:int)
1124
+ @foo = foo
1125
+ end
1126
+ EOF
1127
+
1128
+ assert_equal(0, cls.foo)
1129
+ assert_equal(2, cls.foo_set(2))
1130
+ assert_equal(2, cls.foo)
1131
+ end
1132
+
1133
+ def test_null_is_false
1134
+ cls, = compile("def foo(a:String);if a;true;else;false;end;end")
1135
+ assert_equal(true, cls.foo("a"))
1136
+ assert_equal(false, cls.foo(nil))
1137
+ end
1138
+
1139
+ def test_for
1140
+ cls, = compile(<<-EOF)
1141
+ def foo
1142
+ a = int[3]
1143
+ count = 0
1144
+ for x in a
1145
+ count += 1
1146
+ end
1147
+ count
1148
+ end
1149
+ EOF
1150
+
1151
+ cls, = compile(<<-EOF)
1152
+ def foo(a:int[])
1153
+ count = 0
1154
+ for x in a
1155
+ count += x
1156
+ end
1157
+ count
1158
+ end
1159
+ EOF
1160
+
1161
+ assert_equal(9, cls.foo([2, 3, 4].to_java(:int)))
1162
+ end
1163
+
1164
+ def test_if_expr
1165
+ cls, = compile(<<-EOF)
1166
+ def foo(a:int)
1167
+ return 1 if a == 1
1168
+ end
1169
+
1170
+ def bar(a:int)
1171
+ return 1 unless a == 1
1172
+ end
1173
+ EOF
1174
+
1175
+ assert_equal(0, cls.foo(0))
1176
+ assert_equal(1, cls.foo(1))
1177
+ assert_equal(1, cls.bar(0))
1178
+ assert_equal(0, cls.bar(1))
1179
+ end
1180
+
1181
+ def test_and
1182
+ cls, = compile(<<-EOF)
1183
+ def bool(n:String, x:boolean)
1184
+ puts n
1185
+ x
1186
+ end
1187
+
1188
+ def foo(a:boolean, b:boolean)
1189
+ return bool('a', a) && bool('b', b)
1190
+ end
1191
+
1192
+ def str(n:String, x:String)
1193
+ puts n
1194
+ x
1195
+ end
1196
+
1197
+ def bar(a:String, b:String)
1198
+ return str('a', a) && str('b', b)
1199
+ end
1200
+ EOF
1201
+
1202
+ assert_output("a\n") { assert_equal(false, cls.foo(false, true)) }
1203
+ assert_output("a\nb\n") { assert_equal(false, cls.foo(true, false)) }
1204
+ assert_output("a\nb\n") { assert_equal(true, cls.foo(true, true)) }
1205
+
1206
+ assert_output("a\n") { assert_equal(nil, cls.bar(nil, "B")) }
1207
+ assert_output("a\nb\n") { assert_equal(nil, cls.bar("A", nil)) }
1208
+ assert_output("a\nb\n") { assert_equal("B", cls.bar("A", "B")) }
1209
+
1210
+ cls, = compile(<<-EOF)
1211
+ def s
1212
+ @s
1213
+ end
1214
+
1215
+ def s=(s:String)
1216
+ @s = s
1217
+ end
1218
+
1219
+ def b
1220
+ @b
1221
+ end
1222
+
1223
+ def b=(b:boolean)
1224
+ @b = b
1225
+ end
1226
+
1227
+ def foo(x:boolean)
1228
+ @b &&= x
1229
+ end
1230
+
1231
+ def bar(x:String)
1232
+ @s &&= x
1233
+ end
1234
+ EOF
1235
+
1236
+ cls.b_set(false)
1237
+ assert_equal(false, cls.foo(false))
1238
+ assert_equal(false, cls.b)
1239
+
1240
+ cls.b_set(true)
1241
+ assert_equal(false, cls.foo(false))
1242
+ assert_equal(false, cls.b)
1243
+
1244
+ cls.b_set(true)
1245
+ assert_equal(true, cls.foo(true))
1246
+ assert_equal(true, cls.b)
1247
+
1248
+ cls.s_set(nil)
1249
+ assert_equal(nil, cls.bar(nil))
1250
+ assert_equal(nil, cls.s)
1251
+
1252
+ cls.s_set("S")
1253
+ assert_equal(nil, cls.bar(nil))
1254
+ assert_equal(nil, cls.s)
1255
+
1256
+ cls.s_set("S")
1257
+ assert_equal("x", cls.bar("x"))
1258
+ assert_equal("x", cls.s)
1259
+
1260
+ cls, foo = compile(<<-EOF)
1261
+ class Foo2
1262
+ def initialize
1263
+ @count = 0
1264
+ end
1265
+
1266
+ def count
1267
+ @count
1268
+ end
1269
+
1270
+ def a
1271
+ @a
1272
+ end
1273
+
1274
+ def a=(a:String)
1275
+ @count += 1
1276
+ @a = a
1277
+ end
1278
+
1279
+ def foo(f:Foo2, x:String)
1280
+ f.a &&= x
1281
+ end
1282
+ end
1283
+ EOF
1284
+
1285
+ f = foo.new
1286
+ assert_equal(nil, f.foo(f, 'x'))
1287
+ assert_equal(0, f.count)
1288
+
1289
+ f = foo.new
1290
+ f.a_set("A")
1291
+ assert_equal(nil, f.foo(f, nil))
1292
+ assert_equal(2, f.count)
1293
+
1294
+ f = foo.new
1295
+ f.a_set("A")
1296
+ assert_equal('x', f.foo(f, 'x'))
1297
+ assert_equal(2, f.count)
1298
+ end
1299
+
1300
+ def test_or
1301
+ cls, = compile(<<-EOF)
1302
+ def bool(n:String, x:boolean)
1303
+ puts n
1304
+ x
1305
+ end
1306
+
1307
+ def foo(a:boolean, b:boolean)
1308
+ return bool('a', a) || bool('b', b)
1309
+ end
1310
+
1311
+ def str(n:String, x:String)
1312
+ puts n
1313
+ x
1314
+ end
1315
+
1316
+ def bar(a:String, b:String)
1317
+ return str('a', a) || str('b', b)
1318
+ end
1319
+ EOF
1320
+
1321
+ assert_output("a\n") { assert_equal(true, cls.foo(true, false)) }
1322
+ assert_output("a\nb\n") { assert_equal(false, cls.foo(false, false)) }
1323
+ assert_output("a\nb\n") { assert_equal(true, cls.foo(false, true)) }
1324
+
1325
+ assert_output("a\n") { assert_equal("A", cls.bar("A", nil)) }
1326
+ assert_output("a\nb\n") { assert_equal(nil, cls.bar(nil, nil)) }
1327
+ assert_output("a\nb\n") { assert_equal("B", cls.bar(nil, "B")) }
1328
+
1329
+ cls, = compile(<<-EOF)
1330
+ def s
1331
+ @s
1332
+ end
1333
+
1334
+ def s=(s:String)
1335
+ @s = s
1336
+ end
1337
+
1338
+ def b
1339
+ @b
1340
+ end
1341
+
1342
+ def b=(b:boolean)
1343
+ @b = b
1344
+ end
1345
+
1346
+ def foo(x:boolean)
1347
+ @b ||= x
1348
+ end
1349
+
1350
+ def bar(x:String)
1351
+ @s ||= x
1352
+ end
1353
+ EOF
1354
+
1355
+ cls.b_set(false)
1356
+ assert_equal(false, cls.foo(false))
1357
+ assert_equal(false, cls.b)
1358
+
1359
+ cls.b_set(false)
1360
+ assert_equal(true, cls.foo(true))
1361
+ assert_equal(true, cls.b)
1362
+
1363
+ cls.b_set(true)
1364
+ assert_equal(true, cls.foo(false))
1365
+ assert_equal(true, cls.b)
1366
+
1367
+ cls.s_set(nil)
1368
+ assert_equal(nil, cls.bar(nil))
1369
+ assert_equal(nil, cls.s)
1370
+
1371
+ cls.s_set(nil)
1372
+ assert_equal("x", cls.bar("x"))
1373
+ assert_equal("x", cls.s)
1374
+
1375
+ cls.s_set("S")
1376
+ assert_equal("S", cls.bar("x"))
1377
+ assert_equal("S", cls.s)
1378
+
1379
+ cls, foo = compile(<<-EOF)
1380
+ class Foo3
1381
+ def initialize
1382
+ @count = 0
1383
+ end
1384
+
1385
+ def count
1386
+ @count
1387
+ end
1388
+
1389
+ def a
1390
+ @a
1391
+ end
1392
+
1393
+ def a=(a:String)
1394
+ @count += 1
1395
+ @a = a
1396
+ end
1397
+
1398
+ def foo(f:Foo3, x:String)
1399
+ f.a ||= x
1400
+ end
1401
+ end
1402
+ EOF
1403
+
1404
+ f = foo.new
1405
+ assert_equal('x', f.foo(f, 'x'))
1406
+ assert_equal(1, f.count)
1407
+
1408
+ f = foo.new
1409
+ assert_equal(nil, f.foo(f, nil))
1410
+ assert_equal(1, f.count)
1411
+
1412
+ f = foo.new
1413
+ f.a_set("A")
1414
+ assert_equal("A", f.foo(f, nil))
1415
+ assert_equal(1, f.count)
1416
+
1417
+ f = foo.new
1418
+ f.a_set("A")
1419
+ assert_equal("A", f.foo(f, 'X'))
1420
+ assert_equal(1, f.count)
1421
+ end
1422
+
1423
+ def test_op_elem_assign
1424
+ cls, foo = compile(<<-EOF)
1425
+ class Foo4
1426
+ def initialize
1427
+ @i = -1
1428
+ end
1429
+
1430
+ def i
1431
+ @i += 1
1432
+ end
1433
+
1434
+ def a
1435
+ @a
1436
+ end
1437
+
1438
+ def a=(a:String[])
1439
+ @a = a
1440
+ end
1441
+
1442
+ def foo(x:String)
1443
+ a[i] ||= x
1444
+ end
1445
+
1446
+ def bar(x:String)
1447
+ a[i] &&= x
1448
+ end
1449
+ end
1450
+ EOF
1451
+
1452
+ f = foo.new
1453
+ f.a_set([nil, nil, nil].to_java(:string))
1454
+ assert_equal(nil, f.bar("x"))
1455
+ assert_equal([nil, nil, nil], f.a.to_a)
1456
+ assert_equal("x", f.foo("x"))
1457
+ assert_equal([nil, "x", nil], f.a.to_a)
1458
+ end
1459
+ end