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