rdl 1.1.1 → 2.0.0.rc1
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.
- checksums.yaml +4 -4
- data/CHANGES.md +6 -0
- data/README.md +211 -32
- data/gemfiles/Gemfile.travis +1 -1
- data/lib/rdl.rb +85 -18
- data/lib/rdl/info.rb +74 -0
- data/lib/rdl/query.rb +8 -9
- data/lib/rdl/typecheck.rb +1057 -0
- data/lib/rdl/types/annotated_arg.rb +5 -5
- data/lib/rdl/types/{nil.rb → bot.rb} +9 -13
- data/lib/rdl/types/dependent_arg.rb +5 -5
- data/lib/rdl/types/dots_query.rb +2 -0
- data/lib/rdl/types/finitehash.rb +67 -24
- data/lib/rdl/types/generic.rb +13 -21
- data/lib/rdl/types/intersection.rb +9 -8
- data/lib/rdl/types/method.rb +30 -32
- data/lib/rdl/types/nominal.rb +22 -16
- data/lib/rdl/types/optional.rb +8 -22
- data/lib/rdl/types/parser.racc +8 -3
- data/lib/rdl/types/parser.tab.rb +131 -118
- data/lib/rdl/types/singleton.rb +15 -10
- data/lib/rdl/types/structural.rb +6 -6
- data/lib/rdl/types/top.rb +6 -6
- data/lib/rdl/types/tuple.rb +56 -24
- data/lib/rdl/types/type.rb +9 -0
- data/lib/rdl/types/type_inferencer.rb +1 -1
- data/lib/rdl/types/union.rb +52 -26
- data/lib/rdl/types/var.rb +7 -6
- data/lib/rdl/types/vararg.rb +5 -6
- data/lib/rdl/types/wild_query.rb +9 -2
- data/lib/rdl/util.rb +9 -7
- data/lib/rdl/wrap.rb +90 -72
- data/lib/rdl_types.rb +2 -2
- data/rdl.gemspec +6 -8
- data/test/test_alias.rb +4 -3
- data/test/test_contract.rb +5 -4
- data/test/test_dsl.rb +2 -1
- data/test/test_generic.rb +30 -26
- data/test/test_intersection.rb +3 -3
- data/test/test_le.rb +129 -61
- data/test/test_lib_types.rb +3 -2
- data/test/test_member.rb +33 -46
- data/test/test_parser.rb +113 -116
- data/test/test_query.rb +2 -1
- data/test/test_rdl.rb +64 -6
- data/test/test_rdl_type.rb +3 -2
- data/test/test_type_contract.rb +30 -12
- data/test/test_typecheck.rb +893 -0
- data/test/test_types.rb +50 -54
- data/test/test_wrap.rb +2 -1
- data/types/ruby-2.x/_aliases.rb +13 -2
- data/types/ruby-2.x/bigdecimal.rb +60 -85
- data/types/ruby-2.x/bignum.rb +80 -119
- data/types/ruby-2.x/complex.rb +33 -40
- data/types/ruby-2.x/fixnum.rb +81 -120
- data/types/ruby-2.x/float.rb +79 -116
- data/types/ruby-2.x/integer.rb +187 -22
- data/types/ruby-2.x/nil.rb +12 -0
- data/types/ruby-2.x/numeric.rb +38 -38
- data/types/ruby-2.x/object.rb +3 -3
- data/types/ruby-2.x/random.rb +2 -0
- data/types/ruby-2.x/range.rb +20 -19
- data/types/ruby-2.x/rational.rb +40 -40
- data/types/ruby-2.x/regexp.rb +4 -4
- data/types/ruby-2.x/string.rb +15 -17
- metadata +17 -16
- data/lib/rdl/types/.#lexer.rex +0 -1
data/test/test_query.rb
CHANGED
data/test/test_rdl.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'minitest/autorun'
|
2
|
-
|
2
|
+
$LOAD_PATH << File.dirname(__FILE__) + "/../lib"
|
3
|
+
require 'rdl'
|
3
4
|
|
4
5
|
class TestRDL < Minitest::Test
|
5
6
|
|
@@ -282,11 +283,11 @@ RUBY
|
|
282
283
|
end
|
283
284
|
|
284
285
|
def test_cast
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
286
|
+
obj1 = 3.type_cast($__rdl_nil_type, force: true)
|
287
|
+
assert ($__rdl_nil_type.member? obj1)
|
288
|
+
obj2 = 3.type_cast('nil', force: true)
|
289
|
+
assert ($__rdl_nil_type.member? obj2)
|
290
|
+
assert_raises(RuntimeError) { 3.type_cast($__rdl_nil_type) }
|
290
291
|
end
|
291
292
|
|
292
293
|
def test_pre_post_self
|
@@ -298,4 +299,61 @@ RUBY
|
|
298
299
|
assert_equal 3, m23(3)
|
299
300
|
end
|
300
301
|
|
302
|
+
def test_nowrap
|
303
|
+
pre(TestRDL, :nwrap1) { true }
|
304
|
+
def nwrap1(x) return x; end
|
305
|
+
assert(RDL::Wrap.wrapped?(TestRDL, :nwrap1))
|
306
|
+
pre(TestRDL, :nwrap2, wrap: false) { true }
|
307
|
+
def nwrap2(x) return x; end
|
308
|
+
assert(not(RDL::Wrap.wrapped?(TestRDL, :nwrap2)))
|
309
|
+
|
310
|
+
post(TestRDL, :nwrap3) { true }
|
311
|
+
def nwrap3(x) return x; end
|
312
|
+
assert(RDL::Wrap.wrapped?(TestRDL, :nwrap3))
|
313
|
+
post(TestRDL, :nwrap4, wrap: false) { true }
|
314
|
+
def nwrap4(x) return x; end
|
315
|
+
assert(not(RDL::Wrap.wrapped?(TestRDL, :nwrap4)))
|
316
|
+
|
317
|
+
type TestRDL, :nwrap5, "(Fixnum) -> Fixnum"
|
318
|
+
def nwrap5(x) return x; end
|
319
|
+
assert(RDL::Wrap.wrapped?(TestRDL, :nwrap5))
|
320
|
+
type TestRDL, :nwrap6, "(Fixnum) -> Fixnum", wrap: false
|
321
|
+
def nwrap6(x) return x; end
|
322
|
+
assert(not(RDL::Wrap.wrapped?(TestRDL, :nwrap6)))
|
323
|
+
|
324
|
+
self.class.class_eval {
|
325
|
+
type "(Fixnum) -> Fixnum"
|
326
|
+
def nwrap7(x) return x; end
|
327
|
+
}
|
328
|
+
assert(RDL::Wrap.wrapped?(TestRDL, :nwrap7))
|
329
|
+
self.class.class_eval {
|
330
|
+
type "(Fixnum) -> Fixnum", wrap: false
|
331
|
+
def nwrap8(x) return x; end
|
332
|
+
}
|
333
|
+
assert(not(RDL::Wrap.wrapped?(TestRDL, :nwrap8)))
|
334
|
+
end
|
335
|
+
|
336
|
+
def test_var_type
|
337
|
+
self.class.class_eval {
|
338
|
+
var_type :@foo, "Fixnum"
|
339
|
+
var_type :@@foo, "String"
|
340
|
+
var_type :$foo, "Symbol"
|
341
|
+
}
|
342
|
+
assert_equal $__rdl_fixnum_type, $__rdl_info.get(TestRDL, :@foo, :type)
|
343
|
+
assert_equal $__rdl_string_type, $__rdl_info.get(TestRDL, :@@foo, :type)
|
344
|
+
assert_equal $__rdl_symbol_type, $__rdl_info.get(RDL::Util::GLOBAL_NAME, :$foo, :type)
|
345
|
+
assert_raises(RuntimeError) {
|
346
|
+
self.class.class_eval { var_type :@foo, "String" }
|
347
|
+
}
|
348
|
+
assert_raises(RuntimeError) {
|
349
|
+
self.class.class_eval { var_type :@@foo, "Fixnum" }
|
350
|
+
}
|
351
|
+
assert_raises(RuntimeError) {
|
352
|
+
self.class.class_eval { var_type :Foo, "String" }
|
353
|
+
}
|
354
|
+
assert_raises(RuntimeError) {
|
355
|
+
self.class.class_eval { var_type :$foo, "String" }
|
356
|
+
}
|
357
|
+
end
|
358
|
+
|
301
359
|
end
|
data/test/test_rdl_type.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'minitest/autorun'
|
2
|
-
|
2
|
+
$LOAD_PATH << File.dirname(__FILE__) + "/../lib"
|
3
|
+
require 'rdl'
|
3
4
|
|
4
5
|
class TestRDLType < Minitest::Test
|
5
6
|
def test_single_type_contract
|
@@ -67,4 +68,4 @@ class TestRDLType < Minitest::Test
|
|
67
68
|
assert_raises(RDL::Type::TypeError) { TestRDLType::NI_B.new("3") }
|
68
69
|
end
|
69
70
|
|
70
|
-
end
|
71
|
+
end
|
data/test/test_type_contract.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'minitest/autorun'
|
2
|
-
|
2
|
+
$LOAD_PATH << File.dirname(__FILE__) + "/../lib"
|
3
|
+
require 'rdl'
|
3
4
|
|
4
5
|
class TestTypeContract < Minitest::Test
|
5
6
|
include RDL::Type
|
@@ -8,10 +9,9 @@ class TestTypeContract < Minitest::Test
|
|
8
9
|
def setup
|
9
10
|
@p = Parser.new
|
10
11
|
end
|
11
|
-
|
12
|
+
|
12
13
|
def test_flat
|
13
|
-
|
14
|
-
cnil = tnil.to_contract
|
14
|
+
cnil = $__rdl_nil_type.to_contract
|
15
15
|
assert (cnil.check self, nil)
|
16
16
|
assert_raises(TypeError) { cnil.check self, true }
|
17
17
|
tfixnum = NominalType.new :Fixnum
|
@@ -42,7 +42,7 @@ class TestTypeContract < Minitest::Test
|
|
42
42
|
p3 = t3.to_contract.wrap(self) { nil }
|
43
43
|
assert_nil p3.call
|
44
44
|
assert_raises(TypeError) { p3.call(42) }
|
45
|
-
|
45
|
+
|
46
46
|
t4 = @p.scan_str "(Fixnum, ?Fixnum) -> Fixnum"
|
47
47
|
p4 = t4.to_contract.wrap(self) { |x| x }
|
48
48
|
assert_equal 42, p4.call(42)
|
@@ -125,11 +125,11 @@ class TestTypeContract < Minitest::Test
|
|
125
125
|
assert_raises(TypeError) { p12b.call(9, 10) }
|
126
126
|
|
127
127
|
t13 = @p.scan_str "(Fixnum, {(Fixnum x {{x>10}}) -> Fixnum}) -> Float"
|
128
|
-
p13 = t13.to_higher_contract(self) { |x,y| x+y.call(11)+0.5 }
|
128
|
+
p13 = t13.to_higher_contract(self) { |x,y| x+y.call(11)+0.5 }
|
129
129
|
assert_equal 53.5, p13.call(42, Proc.new { |x| x })
|
130
130
|
assert_raises(TypeError) { p13.call(42.5, Proc.new { |x| x} ) }
|
131
131
|
assert_raises(TypeError) { p13.call(42, Proc.new { |x| 0.5 } ) }
|
132
|
-
p13b = t13.to_higher_contract(self) { |x,y| x+y.call(10)+0.5 }
|
132
|
+
p13b = t13.to_higher_contract(self) { |x,y| x+y.call(10)+0.5 }
|
133
133
|
assert_raises(TypeError) { p13b.call(42, Proc.new { |x| x } ) }
|
134
134
|
p13c = t13.to_higher_contract(self) { |x,y| x+y.call(11.5)+0.5 }
|
135
135
|
assert_raises(TypeError) { p13c.call(42, Proc.new { |x| x } ) }
|
@@ -146,31 +146,49 @@ class TestTypeContract < Minitest::Test
|
|
146
146
|
p14d = p14c.call(42,42)
|
147
147
|
assert_raises(TypeError) { p14d.call(42) }
|
148
148
|
|
149
|
+
#contracts involving method blocks
|
149
150
|
assert_equal 47, block_contract_test1(42) {|z| z}
|
150
|
-
assert_raises(TypeError) { block_contract_test1(42) {|z| 0.5} }
|
151
|
+
assert_raises(TypeError) { block_contract_test1(42) {|z| 0.5} }
|
151
152
|
assert_raises(TypeError) { block_contract_test2(42) {|z| z} }
|
152
|
-
|
153
|
+
assert_raises(TypeError) { block_contract_test1(42) }
|
154
|
+
assert_raises(TypeError) { block_contract_test3(42) { |x| x } }
|
153
155
|
|
154
156
|
t15 = @p.scan_str "(Fixnum x {{x>y}}, Fixnum y) -> Fixnum"
|
155
|
-
p15 = t15.to_contract.wrap(self) { |x, y| x+y }
|
157
|
+
p15 = t15.to_contract.wrap(self) { |x, y| x+y }
|
156
158
|
assert_equal 21, p15.call(11, 10)
|
157
159
|
assert_raises(TypeError) { p15.call(10, 11) }
|
158
160
|
|
159
161
|
t16 = @p.scan_str "(Fixnum x {{x > undefvar}}, Fixnum) -> Fixnum"
|
160
162
|
p16 = t16.to_contract.wrap(self) { |x,y| x }
|
161
|
-
assert_raises(NameError) { p16.call(10,10) }
|
163
|
+
assert_raises(NameError) { p16.call(10,10) }
|
164
|
+
|
165
|
+
t17 = @p.scan_str "(Fixnum, *String, Fixnum) -> Fixnum"
|
166
|
+
p17 = t17.to_contract.wrap(self) { |x| x }
|
167
|
+
assert_equal 42, p17.call(42, 43)
|
168
|
+
assert_equal 42, p17.call(42, 'foo', 43)
|
169
|
+
assert_equal 42, p17.call(42, 'foo', 'bar', 43)
|
170
|
+
assert_raises(TypeError) { p17.call }
|
171
|
+
assert_raises(TypeError) { p17.call('42') }
|
172
|
+
assert_raises(TypeError) { p17.call(42) }
|
173
|
+
assert_raises(TypeError) { p17.call(42, '43') }
|
174
|
+
assert_raises(TypeError) { p17.call(42, 43, '44') }
|
162
175
|
end
|
163
176
|
|
164
177
|
type '(Fixnum) { (Fixnum) -> Fixnum } -> Fixnum'
|
165
178
|
def block_contract_test1(x)
|
166
179
|
x+yield(5)
|
167
180
|
end
|
168
|
-
|
181
|
+
|
169
182
|
type '(Fixnum) { (Fixnum) -> Fixnum } -> Float'
|
170
183
|
def block_contract_test2(x)
|
171
184
|
x+yield(4.5)
|
172
185
|
end
|
173
186
|
|
187
|
+
type '(Fixnum) -> Fixnum'
|
188
|
+
def block_contract_test3(x)
|
189
|
+
42
|
190
|
+
end
|
191
|
+
|
174
192
|
def test_proc_names
|
175
193
|
t1 = @p.scan_str "(x: Fixnum) -> Fixnum"
|
176
194
|
p1 = t1.to_contract.wrap(self) { |x:| x }
|
@@ -0,0 +1,893 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
$LOAD_PATH << File.dirname(__FILE__) + "/../lib"
|
3
|
+
require 'rdl'
|
4
|
+
require 'rdl_types'
|
5
|
+
|
6
|
+
class TestTypecheck < Minitest::Test
|
7
|
+
|
8
|
+
type :_any_object, "() -> Object" # a method that could return true or false
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@t3 = RDL::Type::SingletonType.new 3
|
12
|
+
@t4 = RDL::Type::SingletonType.new 4
|
13
|
+
@t5 = RDL::Type::SingletonType.new 5
|
14
|
+
@t34 = RDL::Type::UnionType.new(@t3, @t4)
|
15
|
+
@t45 = RDL::Type::UnionType.new(@t4, @t5)
|
16
|
+
@t35 = RDL::Type::UnionType.new(@t3, @t5)
|
17
|
+
@t345 = RDL::Type::UnionType.new(@t34, @t5)
|
18
|
+
@ts3 = RDL::Type::UnionType.new($__rdl_string_type, @t3)
|
19
|
+
@ts34 = RDL::Type::UnionType.new(@ts3, @t4)
|
20
|
+
@t3n = RDL::Type::UnionType.new(@t3, $__rdl_nil_type)
|
21
|
+
@t4n = RDL::Type::UnionType.new(@t4, $__rdl_nil_type)
|
22
|
+
@env = RDL::Typecheck::Env.new(self: tt("TestTypecheck"))
|
23
|
+
@scopef = { tret: $__rdl_fixnum_type }
|
24
|
+
@tfs = RDL::Type::UnionType.new($__rdl_fixnum_type, $__rdl_string_type)
|
25
|
+
@scopefs = { tret: @tfs }
|
26
|
+
end
|
27
|
+
|
28
|
+
# [+ a +] is the environment, a map from symbols to types; empty if omitted
|
29
|
+
# [+ expr +] is a string containing the expression to typecheck
|
30
|
+
# returns the type of the expression
|
31
|
+
def do_tc(expr, scope: Hash.new, env: RDL::Typecheck::Env.new)
|
32
|
+
ast = Parser::CurrentRuby.parse expr
|
33
|
+
_, t = RDL::Typecheck.tc scope, env, ast
|
34
|
+
return t
|
35
|
+
end
|
36
|
+
|
37
|
+
# convert arg string to a type
|
38
|
+
def tt(t)
|
39
|
+
$__rdl_parser.scan_str('#T ' + t)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_def
|
43
|
+
self.class.class_eval {
|
44
|
+
type "(Fixnum) -> Fixnum", typecheck_now: true
|
45
|
+
def def_ff(x) x; end
|
46
|
+
}
|
47
|
+
|
48
|
+
assert_raises(RDL::Typecheck::StaticTypeError) {
|
49
|
+
self.class.class_eval {
|
50
|
+
type "(Fixnum) -> Fixnum", typecheck_now: true
|
51
|
+
def def_fs(x) "42"; end
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
self.class.class_eval {
|
56
|
+
type "(Fixnum) -> Fixnum", typecheck_now: true
|
57
|
+
def def_ff2(x) x; end
|
58
|
+
}
|
59
|
+
assert_equal 42, def_ff2(42)
|
60
|
+
|
61
|
+
self.class.class_eval {
|
62
|
+
type "(Fixnum) -> Fixnum", typecheck: true
|
63
|
+
def def_fs2(x) "42"; end
|
64
|
+
}
|
65
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { def_fs2(42) }
|
66
|
+
|
67
|
+
assert_raises(RDL::Typecheck::StaticTypeError) {
|
68
|
+
self.class.class_eval {
|
69
|
+
type "(Fixnum) -> Fixnum", typecheck_now: true
|
70
|
+
def def_ff3(x, y) 42; end
|
71
|
+
}
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_defs
|
76
|
+
self.class.class_eval {
|
77
|
+
type "(Fixnum) -> Class", typecheck_now: true
|
78
|
+
def self.defs_ff(x) self; end
|
79
|
+
}
|
80
|
+
|
81
|
+
self.class.class_eval {
|
82
|
+
type "() -> Class", typecheck_now: true
|
83
|
+
def self.defs_nn() defs_ff(42); end
|
84
|
+
}
|
85
|
+
|
86
|
+
assert_raises(RDL::Typecheck::StaticTypeError) {
|
87
|
+
self.class.class_eval {
|
88
|
+
type "() -> Class", typecheck_now: true
|
89
|
+
def self.defs_other() fdsakjfhds(42); end
|
90
|
+
}
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_lits
|
95
|
+
assert_equal $__rdl_nil_type, do_tc("nil")
|
96
|
+
assert_equal $__rdl_true_type, do_tc("true")
|
97
|
+
assert_equal $__rdl_false_type, do_tc("false")
|
98
|
+
assert_equal tt("42"), do_tc("42")
|
99
|
+
assert do_tc("123456789123456789123456789") <= $__rdl_bignum_type
|
100
|
+
assert_equal tt("3.14"), do_tc("3.14")
|
101
|
+
assert_equal $__rdl_complex_type, do_tc("1i")
|
102
|
+
assert_equal $__rdl_rational_type, do_tc("2.0r")
|
103
|
+
assert_equal $__rdl_string_type, do_tc("'42'")
|
104
|
+
assert_equal $__rdl_string_type, do_tc("\"42\"")
|
105
|
+
assert_equal tt(":foo"), do_tc(":foo")
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_empty
|
109
|
+
self.class.class_eval {
|
110
|
+
type "() -> nil", typecheck_now: true
|
111
|
+
def empty() end
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_dstr_xstr
|
116
|
+
# Hard to read if these are inside of strings, so leave like this
|
117
|
+
self.class.class_eval {
|
118
|
+
type "() -> String", typecheck_now: true
|
119
|
+
def dstr() "Foo #{42} Bar #{43}"; end
|
120
|
+
|
121
|
+
type "() -> String", typecheck_now: true
|
122
|
+
def xstr() `ls #{42}`; end
|
123
|
+
}
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_seq
|
127
|
+
assert_equal $__rdl_string_type, do_tc("_ = 42; _ = 43; 'foo'")
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_dsym
|
131
|
+
# Hard to read if these are inside of strings, so leave like this
|
132
|
+
self.class.class_eval {
|
133
|
+
type "() -> Symbol", typecheck_now: true
|
134
|
+
def dsym() :"foo#{42}"; end
|
135
|
+
}
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_regexp
|
139
|
+
assert_equal $__rdl_regexp_type, do_tc("/foo/")
|
140
|
+
|
141
|
+
self.class.class_eval {
|
142
|
+
# Hard to read if these are inside of strings, so leave like this
|
143
|
+
type "() -> Regexp", typecheck_now: true
|
144
|
+
def regexp2() /foo#{42}bar#{"baz"}/i; end
|
145
|
+
}
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_tuple
|
149
|
+
assert_equal tt("[TrueClass, String]"), do_tc("[true, '42']")
|
150
|
+
assert_equal tt("[42, String]"), do_tc("[42, '42']")
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_hash
|
154
|
+
assert_equal tt("{x: TrueClass, y: FalseClass}"), do_tc("{x: true, y: false}")
|
155
|
+
assert_equal tt("Hash<String, 1 or 2>"), do_tc("{'a' => 1, 'b' => 2}")
|
156
|
+
assert_equal tt("{1 => String, 2 => String}"), do_tc("{1 => 'a', 2 => 'b'}")
|
157
|
+
assert_equal tt("{}"), do_tc("{}")
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_range
|
161
|
+
assert_equal tt("Range<Fixnum>"), do_tc("1..5")
|
162
|
+
assert_equal tt("Range<Fixnum>"), do_tc("1...5")
|
163
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("1..'foo'") }
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_self
|
167
|
+
# These need to be inside an actual class
|
168
|
+
self.class.class_eval {
|
169
|
+
type "() -> self", typecheck_now: true
|
170
|
+
def self1() self; end
|
171
|
+
}
|
172
|
+
|
173
|
+
self.class.class_eval {
|
174
|
+
type "() -> self", typecheck_now: true
|
175
|
+
def self2() TestTypecheck.new; end
|
176
|
+
}
|
177
|
+
|
178
|
+
assert_raises(RDL::Typecheck::StaticTypeError) {
|
179
|
+
self.class.class_eval {
|
180
|
+
type "() -> self", typecheck_now: true
|
181
|
+
def self3() Object.new; end
|
182
|
+
}
|
183
|
+
}
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_nth_back
|
187
|
+
assert_equal $__rdl_string_type, do_tc("$4")
|
188
|
+
assert_equal $__rdl_string_type, do_tc("$+")
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_const
|
192
|
+
assert_equal tt("${String}"), do_tc("String", env: @env)
|
193
|
+
assert_equal $__rdl_nil_type, do_tc("NIL", env: @env)
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_defined
|
197
|
+
assert_equal $__rdl_string_type, do_tc("defined?(x)")
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_lvar
|
201
|
+
self.class.class_eval {
|
202
|
+
type "(Fixnum, String) -> Fixnum", typecheck_now: true
|
203
|
+
def lvar1(x, y) x; end
|
204
|
+
}
|
205
|
+
|
206
|
+
self.class.class_eval {
|
207
|
+
type "(Fixnum, String) -> String", typecheck_now: true
|
208
|
+
def lvar2(x, y) y; end
|
209
|
+
}
|
210
|
+
|
211
|
+
assert_raises(RDL::Typecheck::StaticTypeError) {
|
212
|
+
# really a send
|
213
|
+
self.class.class_eval {
|
214
|
+
type "(Fixnum, String) -> String", typecheck_now: true
|
215
|
+
def lvar3(x, y) z; end
|
216
|
+
}
|
217
|
+
}
|
218
|
+
end
|
219
|
+
|
220
|
+
def test_lvasgn
|
221
|
+
assert_equal tt("42"), do_tc("x = 42; x")
|
222
|
+
assert_equal tt("42"), do_tc("x = 42; y = x; y")
|
223
|
+
assert_equal tt("42"), do_tc("x = y = 42; x")
|
224
|
+
assert_equal $__rdl_nil_type, do_tc("x = x") # weird behavior - lhs bound to nil always before assignment!
|
225
|
+
end
|
226
|
+
|
227
|
+
def test_lvar_type
|
228
|
+
# var_type arg type and formattests
|
229
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("var_type :x", env: @env) }
|
230
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("var_type :x, 3", env: @env) }
|
231
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("var_type 'x', 'Fixnum'", env: @env) }
|
232
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("var_type :@x, 'Fixnum'", env: @env) }
|
233
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("var_type :x, 'Fluffy Bunny'", env: @env) }
|
234
|
+
|
235
|
+
assert_equal $__rdl_fixnum_type, do_tc("var_type :x, 'Fixnum'; x = 3; x", env: @env)
|
236
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("var_type :x, 'Fixnum'; x = 'three'", env: @env) }
|
237
|
+
self.class.class_eval {
|
238
|
+
type "(Fixnum) -> nil", typecheck_now: true
|
239
|
+
def lvar_type_ff(x) x = 42; nil; end
|
240
|
+
}
|
241
|
+
assert_raises(RDL::Typecheck::StaticTypeError) {
|
242
|
+
self.class.class_eval {
|
243
|
+
type "(Fixnum) -> nil", typecheck_now: true
|
244
|
+
def lvar_type_ff2(x) x = "forty-two"; nil; end
|
245
|
+
}
|
246
|
+
}
|
247
|
+
end
|
248
|
+
|
249
|
+
def test_ivar_ivasgn
|
250
|
+
self.class.class_eval {
|
251
|
+
var_type :@foo, "Fixnum"
|
252
|
+
var_type :@@foo, "Fixnum"
|
253
|
+
var_type :$test_ivar_ivasgn_global, "Fixnum"
|
254
|
+
var_type :@object, "Object"
|
255
|
+
}
|
256
|
+
|
257
|
+
assert_equal $__rdl_fixnum_type, do_tc("@foo", env: @env)
|
258
|
+
assert_equal $__rdl_fixnum_type, do_tc("@@foo", env: @env)
|
259
|
+
assert_equal $__rdl_fixnum_type, do_tc("$test_ivar_ivasgn_global")
|
260
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("@bar", env: @env) }
|
261
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("@bar", env: @env) }
|
262
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("@@bar", env: @env) }
|
263
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("$_test_ivar_ivasgn_global_2") }
|
264
|
+
|
265
|
+
assert_equal @t3, do_tc("@foo = 3", env: @env)
|
266
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("@foo = 'three'", env: @env) }
|
267
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("@bar = 'three'", env: @env) }
|
268
|
+
assert_equal @t3, do_tc("@@foo = 3", env: @env)
|
269
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("@@foo = 'three'", env: @env) }
|
270
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("@@bar = 'three'", env: @env) }
|
271
|
+
assert_equal @t3, do_tc("$test_ivar_ivasgn_global = 3")
|
272
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("$test_ivar_ivasgn_global = 'three'") }
|
273
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("$test_ivar_ivasgn_global_2 = 'three'") }
|
274
|
+
assert_equal @t3, do_tc("@object = 3", env: @env) # type of assignment is type of rhs
|
275
|
+
end
|
276
|
+
|
277
|
+
def test_send_basic
|
278
|
+
self.class.class_eval {
|
279
|
+
type :_send_basic2, "() -> Fixnum"
|
280
|
+
type :_send_basic3, "(Fixnum) -> Fixnum"
|
281
|
+
type :_send_basic4, "(Fixnum, String) -> Fixnum"
|
282
|
+
type "self._send_basic5", "(Fixnum) -> Fixnum"
|
283
|
+
}
|
284
|
+
|
285
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("z", env: @env) }
|
286
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_basic2", env: @env)
|
287
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_basic3(42)", env: @env)
|
288
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_basic3('42')", env: @env) }
|
289
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_basic4(42, '42')", env: @env)
|
290
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_basic4(42, 43)", env: @env) }
|
291
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_basic4('42', '43')", env: @env) }
|
292
|
+
assert_equal $__rdl_fixnum_type, do_tc("TestTypecheck._send_basic5(42)", env: @env)
|
293
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("TestTypecheck._send_basic5('42')", env: @env) }
|
294
|
+
assert_equal $__rdl_nil_type, do_tc("puts 42", env: @env)
|
295
|
+
end
|
296
|
+
|
297
|
+
class A
|
298
|
+
type :_send_inherit1, "() -> Fixnum"
|
299
|
+
end
|
300
|
+
class B < A
|
301
|
+
end
|
302
|
+
|
303
|
+
class A1
|
304
|
+
type "() -> nil"
|
305
|
+
def _send_inherit2; end
|
306
|
+
end
|
307
|
+
class A2 < A1
|
308
|
+
def _send_inherit2; end
|
309
|
+
end
|
310
|
+
class A3 < A2
|
311
|
+
end
|
312
|
+
|
313
|
+
def test_send_inherit
|
314
|
+
assert_equal $__rdl_fixnum_type, do_tc("B.new._send_inherit1", env: @env)
|
315
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("A3.new._send_inherit2", env: @env) }
|
316
|
+
end
|
317
|
+
|
318
|
+
def test_send_inter
|
319
|
+
self.class.class_eval {
|
320
|
+
type :_send_inter1, "(Fixnum) -> Fixnum"
|
321
|
+
type :_send_inter1, "(String) -> String"
|
322
|
+
}
|
323
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_inter1(42)", env: @env)
|
324
|
+
assert_equal $__rdl_string_type, do_tc("_send_inter1('42')", env: @env)
|
325
|
+
|
326
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("_send_inter1(:forty_two)", env: @env) }
|
327
|
+
end
|
328
|
+
|
329
|
+
def test_send_opt_varargs
|
330
|
+
# from test_type_contract.rb
|
331
|
+
self.class.class_eval {
|
332
|
+
type :_send_opt_varargs1, "(Fixnum, ?Fixnum) -> Fixnum"
|
333
|
+
type :_send_opt_varargs2, "(Fixnum, *Fixnum) -> Fixnum"
|
334
|
+
type :_send_opt_varargs3, "(Fixnum, ?Fixnum, ?Fixnum, *Fixnum) -> Fixnum"
|
335
|
+
type :_send_opt_varargs4, "(?Fixnum) -> Fixnum"
|
336
|
+
type :_send_opt_varargs5, "(*Fixnum) -> Fixnum"
|
337
|
+
type :_send_opt_varargs6, "(?Fixnum, String) -> Fixnum"
|
338
|
+
type :_send_opt_varargs7, "(Fixnum, *String, Fixnum) -> Fixnum"
|
339
|
+
}
|
340
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs1(42)", env: @env)
|
341
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs1(42, 43)", env: @env)
|
342
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs1()", env: @env) }
|
343
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs1(42, 43, 44)", env: @env) }
|
344
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs2(42)", env: @env)
|
345
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs2(42, 43)", env: @env)
|
346
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs2(42, 43, 44)", env: @env)
|
347
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs2(42, 43, 44, 45)", env: @env)
|
348
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs2()", env: @env) }
|
349
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs2('42')", env: @env) }
|
350
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs2(42, '43')", env: @env) }
|
351
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs2(42, 43, '44')", env: @env) }
|
352
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs2(42, 43, 44, '45')", env: @env) }
|
353
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs3(42)", env: @env)
|
354
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs3(42, 43)", env: @env)
|
355
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs3(42, 43, 44)", env: @env)
|
356
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs3(42, 43, 45)", env: @env)
|
357
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs3(42, 43, 46)", env: @env)
|
358
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs3()", env: @env) }
|
359
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs3('42')", env: @env) }
|
360
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs3(42, '43')", env: @env) }
|
361
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs3(42, 43, '44')", env: @env) }
|
362
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs3(42, 43, 44, '45')", env: @env) }
|
363
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs3(42, 43, 44, 45, '46')", env: @env) }
|
364
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs4()", env: @env)
|
365
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs4(42)", env: @env)
|
366
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs4('42')", env: @env) }
|
367
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs4(42, 43)", env: @env) }
|
368
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs4(42, 43, 44)", env: @env) }
|
369
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs5()", env: @env)
|
370
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs5(42)", env: @env)
|
371
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs5(42, 43)", env: @env)
|
372
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs5(42, 43, 44)", env: @env)
|
373
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs5('42')", env: @env) }
|
374
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs5(42, '43')", env: @env) }
|
375
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs5(42, 43, '44')", env: @env) }
|
376
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs6('44')", env: @env)
|
377
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs6(43, '44')", env: @env)
|
378
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs6()", env: @env) }
|
379
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_opt_varargs6(43, '44', 45)", env: @env) }
|
380
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs7(42, 43)", env: @env)
|
381
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs7(42, 'foo', 43)", env: @env)
|
382
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_opt_varargs7(42, 'foo', 'bar', 43)", env: @env)
|
383
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("_send_opt_varargs7", env: @env) }
|
384
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("_send_opt_varargs7('42')", env: @env) }
|
385
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("_send_opt_varargs7(42)", env: @env) }
|
386
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("_send_opt_varargs7(42, '43')", env: @env) }
|
387
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("_send_opt_varargs7(42, '43', '44')", env: @env) }
|
388
|
+
end
|
389
|
+
|
390
|
+
def test_send_named_args
|
391
|
+
# from test_type_contract.rb
|
392
|
+
self.class.class_eval {
|
393
|
+
type :_send_named_args1, "(x: Fixnum) -> Fixnum"
|
394
|
+
type :_send_named_args2, "(x: Fixnum, y: String) -> Fixnum"
|
395
|
+
type :_send_named_args3, "(Fixnum, y: String) -> Fixnum"
|
396
|
+
type :_send_named_args4, "(Fixnum, x: Fixnum, y: String) -> Fixnum"
|
397
|
+
type :_send_named_args5, "(x: Fixnum, y: ?String) -> Fixnum"
|
398
|
+
type :_send_named_args6, "(x: ?Fixnum, y: String) -> Fixnum"
|
399
|
+
type :_send_named_args7, "(x: ?Fixnum, y: ?String) -> Fixnum"
|
400
|
+
type :_send_named_args8, "(?Fixnum, x: ?Symbol, y: ?String) -> Fixnum"
|
401
|
+
}
|
402
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args1(x: 42)", env: @env)
|
403
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args1(x: '42')", env: @env) }
|
404
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args1()", env: @env) }
|
405
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args1(x: 42, y: 42)", env: @env) }
|
406
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args1(y: 42)", env: @env) }
|
407
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args1(42)", env: @env) }
|
408
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args1(42, x: '42')", env: @env) }
|
409
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args2(x: 42, y: '43')", env: @env)
|
410
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args2()", env: @env) }
|
411
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args2(x: 42)", env: @env) }
|
412
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args2(x: '42', y: '43')", env: @env) }
|
413
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args2(42, '43')", env: @env) }
|
414
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args2(42, x: 42, y: '43')", env: @env) }
|
415
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args2(x: 42, y: '43', z: 44)", env: @env) }
|
416
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args3(42, y: '43')", env: @env)
|
417
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args3(42, y: 43)", env: @env) }
|
418
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args3()", env: @env) }
|
419
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args3(42, 43, y: 44)", env: @env) }
|
420
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args3(42, y: 43, z: 44)", env: @env) }
|
421
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args4(42, x: 43, y: '44')", env: @env)
|
422
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args4(42, x: 43)", env: @env) }
|
423
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args4(42, y: '43')", env: @env) }
|
424
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args4()", env: @env) }
|
425
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args4(42, 43, x: 44, y: '45')", env: @env) }
|
426
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args4(42, x: 43, y: '44', z: 45)", env: @env) }
|
427
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args5(x: 42, y: '43')", env: @env)
|
428
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args5(x: 42)", env: @env)
|
429
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args5()", env: @env) }
|
430
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args5(x: 42, y: 43)", env: @env) }
|
431
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args5(x: 42, y: 43, z: 44)", env: @env) }
|
432
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args5(3, x: 42, y: 43)", env: @env) }
|
433
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args5(3, x: 42)", env: @env) }
|
434
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args6(x: 43, y: '44')", env: @env)
|
435
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args6(y: '44')", env: @env)
|
436
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args6()", env: @env) }
|
437
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args6(x: '43', y: '44')", env: @env) }
|
438
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args6(42, x: 43, y: '44')", env: @env) }
|
439
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args6(x: 43, y: '44', z: 45)", env: @env) }
|
440
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args7()", env: @env)
|
441
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args7(x: 43)", env: @env)
|
442
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args7(y: '44')", env: @env)
|
443
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args7(x: 43, y: '44')", env: @env)
|
444
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args7(x: '43', y: '44')", env: @env) }
|
445
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args7(41, x: 43, y: '44')", env: @env) }
|
446
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args7(x: 43, y: '44', z: 45)", env: @env) }
|
447
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args8()", env: @env)
|
448
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args8(43)", env: @env)
|
449
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args8(x: :foo)", env: @env)
|
450
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args8(43, x: :foo)", env: @env)
|
451
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args8(y: 'foo')", env: @env)
|
452
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args8(43, y: 'foo')", env: @env)
|
453
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args8(x: :foo, y: 'foo')", env: @env)
|
454
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_named_args8(43, x: :foo, y: 'foo')", env: @env)
|
455
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args8(43, 44, x: :foo, y: 'foo')", env: @env) }
|
456
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args8(43, x: 'foo', y: 'foo')", env: @env) }
|
457
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { assert do_tc("_send_named_args8(43, x: :foo, y: 'foo', z: 44)", env: @env) }
|
458
|
+
end
|
459
|
+
|
460
|
+
def test_send_singleton
|
461
|
+
type Fixnum, :_send_singleton, "() -> String"
|
462
|
+
assert_equal $__rdl_string_type, do_tc("3._send_singleton", env: @env)
|
463
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("3._send_singleton_nexists", env: @env) }
|
464
|
+
end
|
465
|
+
|
466
|
+
def test_send_generic
|
467
|
+
assert_equal $__rdl_fixnum_type, do_tc("[1,2,3].length", env: @env)
|
468
|
+
assert_equal $__rdl_fixnum_type, do_tc("{a:1, b:2}.length", env: @env)
|
469
|
+
assert_equal $__rdl_string_type, do_tc("String.new.clone", env: @env)
|
470
|
+
# TODO test case with other generic
|
471
|
+
end
|
472
|
+
|
473
|
+
def test_send_alias
|
474
|
+
assert_equal $__rdl_fixnum_type, do_tc("[1,2,3].size", env: @env)
|
475
|
+
end
|
476
|
+
|
477
|
+
def test_send_block
|
478
|
+
self.class.class_eval {
|
479
|
+
type :_send_block1, "(Fixnum) { (Fixnum) -> Fixnum } -> Fixnum"
|
480
|
+
type :_send_block2, "(Fixnum) -> Fixnum"
|
481
|
+
}
|
482
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("_send_block1(42)", env: @env) }
|
483
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("_send_block2(42) { |x| x + 1 }", env: @env) }
|
484
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("_send_block1(42) { |x, y| x + y }", env: @env) }
|
485
|
+
assert_equal $__rdl_fixnum_type, do_tc("_send_block1(42) { |x| x }", env: @env)
|
486
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("_send_block1(42) { |x| 'forty-two' }", env: @env) }
|
487
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x = 1; _send_block1(42) { |y| x }", env: @env) }
|
488
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x = 1; _send_block1(42) { |y| x = 2 }", env: @env) }
|
489
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x = 1; _send_block1(42) { |y| for x in 1..5 do end }", env: @env) } # odd case...
|
490
|
+
end
|
491
|
+
|
492
|
+
def test_send_union
|
493
|
+
assert_equal RDL::Type::UnionType.new(@tfs, $__rdl_bignum_type), do_tc("(if _any_object then Fixnum.new else String.new end) * 2", env: @env)
|
494
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("(if _any_object then Object.new else Fixnum.new end) + 2", env: @env) }
|
495
|
+
end
|
496
|
+
|
497
|
+
def test_send_splat
|
498
|
+
self.class.class_eval {
|
499
|
+
type :_send_splat1, "(Fixnum, String, Fixnum, String) -> Fixnum"
|
500
|
+
type :_send_splat2, "(String, *Fixnum, Float) -> Fixnum"
|
501
|
+
type :_send_splat_fa, "() -> Array<Fixnum>"
|
502
|
+
}
|
503
|
+
assert_equal $__rdl_fixnum_type, do_tc("x = ['foo', 42]; _send_splat1(1, *x, 'bar')", env: @env)
|
504
|
+
assert_equal $__rdl_fixnum_type, do_tc("x = _send_splat_fa; _send_splat2('foo', *x, 3.14)", env: @env)
|
505
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x = _send_splat_fa; _send_splat1(*x, 'foo', 2, 'bar')", env: @env) }
|
506
|
+
end
|
507
|
+
|
508
|
+
|
509
|
+
def test_yield
|
510
|
+
self.class.class_eval {
|
511
|
+
type "(Fixnum) { (Fixnum) -> Fixnum } -> Fixnum", typecheck_now: true
|
512
|
+
def _yield1(x)
|
513
|
+
yield x
|
514
|
+
end
|
515
|
+
}
|
516
|
+
|
517
|
+
assert_raises(RDL::Typecheck::StaticTypeError) {
|
518
|
+
self.class.class_eval {
|
519
|
+
type "(Fixnum) { (Fixnum) -> Fixnum } -> Fixnum", typecheck_now: true
|
520
|
+
def _yield2(x)
|
521
|
+
yield 'forty-two'
|
522
|
+
end
|
523
|
+
}
|
524
|
+
}
|
525
|
+
|
526
|
+
assert_raises(RDL::Typecheck::StaticTypeError) {
|
527
|
+
self.class.class_eval {
|
528
|
+
type "(Fixnum) { (Fixnum) -> String } -> Fixnum", typecheck_now: true
|
529
|
+
def _yield3(x)
|
530
|
+
yield 42
|
531
|
+
end
|
532
|
+
}
|
533
|
+
}
|
534
|
+
|
535
|
+
assert_raises(RDL::Typecheck::StaticTypeError) {
|
536
|
+
self.class.class_eval {
|
537
|
+
type "(Fixnum) -> Fixnum", typecheck_now: true
|
538
|
+
def _yield4(x)
|
539
|
+
yield 42
|
540
|
+
end
|
541
|
+
}
|
542
|
+
}
|
543
|
+
|
544
|
+
assert_raises(RDL::Typecheck::StaticTypeError) {
|
545
|
+
self.class.class_eval {
|
546
|
+
type "(Fixnum) { (Fixnum) { (Fixnum) -> Fixnum } -> Fixnum } -> Fixnum", typecheck_now: true
|
547
|
+
def _yield5(x)
|
548
|
+
yield 42
|
549
|
+
end
|
550
|
+
}
|
551
|
+
}
|
552
|
+
end
|
553
|
+
|
554
|
+
# class Sup1
|
555
|
+
# type '(Fixnum) -> Fixnum', typecheck: true
|
556
|
+
# def foo(y)
|
557
|
+
# return y
|
558
|
+
# end
|
559
|
+
# end
|
560
|
+
#
|
561
|
+
# class Sup2 < Sup1
|
562
|
+
# type '(Fixnum) -> Fixnum', typecheck: true
|
563
|
+
# def foo(x)
|
564
|
+
# super(x+1)
|
565
|
+
# end
|
566
|
+
# end
|
567
|
+
#
|
568
|
+
# def test_super
|
569
|
+
# assert_equal 43, Sup2.new.foo(42)
|
570
|
+
# end
|
571
|
+
|
572
|
+
def test_new
|
573
|
+
assert_equal RDL::Type::NominalType.new(B), do_tc("B.new", env: @env)
|
574
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("B.new(3)", env: @env) }
|
575
|
+
end
|
576
|
+
|
577
|
+
def test_if
|
578
|
+
assert_equal @t3n, do_tc("if _any_object then 3 end", env: @env)
|
579
|
+
assert_equal @t3n, do_tc("unless _any_object then 3 end", env: @env)
|
580
|
+
assert_equal @t34, do_tc("if _any_object then 3 else 4 end", env: @env)
|
581
|
+
assert_equal @t34, do_tc("unless _any_object then 3 else 4 end", env: @env)
|
582
|
+
assert_equal @ts3, do_tc("if _any_object then 3 else 'three' end", env: @env)
|
583
|
+
assert_equal @ts3, do_tc("unless _any_object then 3 else 'three' end", env: @env)
|
584
|
+
assert_equal @t3n, do_tc("3 if _any_object", env: @env)
|
585
|
+
assert_equal @t3n, do_tc("3 unless _any_object", env: @env)
|
586
|
+
assert_equal @t3, do_tc("if true then 3 else 'three' end", env: @env)
|
587
|
+
assert_equal @t3, do_tc("if :foo then 3 else 'three' end", env: @env)
|
588
|
+
assert_equal $__rdl_string_type, do_tc("if false then 3 else 'three' end", env: @env)
|
589
|
+
assert_equal $__rdl_string_type, do_tc("if nil then 3 else 'three' end", env: @env)
|
590
|
+
|
591
|
+
assert_equal @t45, do_tc("x = 'three'; if _any_object then x = 4 else x = 5 end; x", env: @env)
|
592
|
+
assert_equal @ts3, do_tc("x = 'three'; if _any_object then x = 3 end; x", env: @env)
|
593
|
+
assert_equal @ts3, do_tc("x = 'three'; unless _any_object then x = 3 end; x", env: @env)
|
594
|
+
assert_equal @t4n, do_tc("if _any_object then y = 4 end; y", env: @env) # vars are nil if not defined on branch
|
595
|
+
assert_equal @t35, do_tc("if _any_object then x = 3; y = 4 else x = 5 end; x", env: @env)
|
596
|
+
assert_equal @t4n, do_tc("if _any_object then x = 3; y = 4 else x = 5 end; y", env: @env)
|
597
|
+
end
|
598
|
+
|
599
|
+
def test_and_or
|
600
|
+
assert_equal @ts3, do_tc("'foo' and 3")
|
601
|
+
assert_equal @ts3, do_tc("'foo' && 3")
|
602
|
+
assert_equal $__rdl_string_type, do_tc("3 and 'foo'")
|
603
|
+
assert_equal $__rdl_nil_type, do_tc("nil and 'foo'")
|
604
|
+
assert_equal $__rdl_false_type, do_tc("false and 'foo'")
|
605
|
+
assert_equal @ts3, do_tc("(x = 'foo') and (x = 3); x")
|
606
|
+
assert_equal $__rdl_string_type, do_tc("(x = 3) and (x = 'foo'); x")
|
607
|
+
assert_equal $__rdl_nil_type, do_tc("(x = nil) and (x = 'foo'); x")
|
608
|
+
assert_equal $__rdl_false_type, do_tc("(x = false) and (x = 'foo'); x")
|
609
|
+
|
610
|
+
assert_equal @ts3, do_tc("'foo' or 3")
|
611
|
+
assert_equal @ts3, do_tc("'foo' || 3")
|
612
|
+
assert_equal @t3, do_tc("3 or 'foo'")
|
613
|
+
assert_equal @t3, do_tc("nil or 3")
|
614
|
+
assert_equal @t3, do_tc("false or 3")
|
615
|
+
assert_equal @ts3, do_tc("(x = 'foo') or (x = 3); x")
|
616
|
+
assert_equal @t3, do_tc("(x = 3) or (x = 'foo'); x")
|
617
|
+
assert_equal @t3, do_tc("(x = nil) or (x = 3); x")
|
618
|
+
assert_equal @t3, do_tc("(x = false) or (x = 3); x")
|
619
|
+
end
|
620
|
+
|
621
|
+
class C
|
622
|
+
type :===, "(Object) -> %bool"
|
623
|
+
end
|
624
|
+
|
625
|
+
class D
|
626
|
+
type :===, "(String) -> %bool"
|
627
|
+
end
|
628
|
+
|
629
|
+
def test_when
|
630
|
+
assert_equal @t3, do_tc("case when C.new then 3 end", env: @env)
|
631
|
+
assert_equal @t34, do_tc("x = 4; case when _any_object then x = 3 end; x", env: @env)
|
632
|
+
assert_equal @ts3, do_tc("case when _any_object then 3 else 'foo' end", env: @env)
|
633
|
+
assert_equal @ts3, do_tc("x = 4; case when _any_object then x = 3 else x = 'foo' end; x", env: @env)
|
634
|
+
|
635
|
+
assert_equal $__rdl_string_type, do_tc("case _any_object when C.new then 'foo' end", env: @env)
|
636
|
+
assert_equal @ts3, do_tc("x = 3; case _any_object when C.new then x = 'foo' end; x", env: @env)
|
637
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("case _any_object when D.new then 'foo' end", env: @env) }
|
638
|
+
assert_equal @ts3, do_tc("case _any_object when C.new then 'foo' else 3 end", env: @env)
|
639
|
+
assert_equal @ts3, do_tc("x = 4; case _any_object when C.new then x = 'foo' else x = 3 end; x", env: @env)
|
640
|
+
assert_equal @ts34, do_tc("case _any_object when C.new then 'foo' when C.new then 4 else 3 end", env: @env)
|
641
|
+
assert_equal @ts34, do_tc("x = 5; case _any_object when C.new then x = 'foo' when C.new then x = 4 else x = 3 end; x", env: @env)
|
642
|
+
|
643
|
+
assert_equal @t3, do_tc("case when (x = 3) then 'foo' end; x", env: @env)
|
644
|
+
assert_equal @t34, do_tc("case when (x = 3), (x = 4) then 'foo' end; x", env: @env)
|
645
|
+
assert_equal @t34, do_tc("case when (x = 3), (x = 4) then 'foo' end; x", env: @env)
|
646
|
+
assert_equal @t34, do_tc("case when (x = 4) then x = 3 end; x", env: @env)
|
647
|
+
assert_equal @t34, do_tc("x = 5; case when (x = 3) then 'foo' when (x = 4) then 'foo' end; x", env: @env) # first guard always executed!
|
648
|
+
assert_equal @t345, do_tc("x = 6; case when (x = 3) then 'foo' when (x = 4) then 'foo' else x = 5 end; x", env: @env)
|
649
|
+
end
|
650
|
+
|
651
|
+
def test_while_until
|
652
|
+
# TODO these don't do a great job checking control flow
|
653
|
+
assert_equal $__rdl_nil_type, do_tc("while true do end")
|
654
|
+
assert_equal $__rdl_nil_type, do_tc("until false do end")
|
655
|
+
assert_equal $__rdl_nil_type, do_tc("begin end while true")
|
656
|
+
assert_equal $__rdl_nil_type, do_tc("begin end until false")
|
657
|
+
assert_equal $__rdl_integer_type, do_tc("i = 0; while i < 5 do i = 1 + i end; i")
|
658
|
+
assert_equal $__rdl_integer_type, do_tc("i = 0; while i < 5 do i = i + 1 end; i")
|
659
|
+
assert_equal $__rdl_integer_type, do_tc("i = 0; until i >= 5 do i = 1 + i end; i")
|
660
|
+
assert_equal $__rdl_integer_type, do_tc("i = 0; until i >= 5 do i = i + 1 end; i")
|
661
|
+
assert_equal $__rdl_integer_type, do_tc("i = 0; begin i = 1 + i end while i < 5; i")
|
662
|
+
assert_equal $__rdl_integer_type, do_tc("i = 0; begin i = i + 1 end while i < 5; i")
|
663
|
+
assert_equal $__rdl_integer_type, do_tc("i = 0; begin i = 1 + i end until i >= 5; i")
|
664
|
+
assert_equal $__rdl_integer_type, do_tc("i = 0; begin i = i + 1 end until i >= 5; i")
|
665
|
+
|
666
|
+
# break, redo, next, no args
|
667
|
+
assert_equal $__rdl_integer_type, do_tc("i = 0; while i < 5 do if i > 2 then break end; i = 1 + i end; i")
|
668
|
+
assert_equal tt("0"), do_tc("i = 0; while i < 5 do break end; i")
|
669
|
+
assert_equal tt("0"), do_tc("i = 0; while i < 5 do redo end; i") # infinite loop, ok for typing
|
670
|
+
assert_equal tt("0"), do_tc("i = 0; while i < 5 do next end; i") # infinite loop, ok for typing
|
671
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("i = 0; while i < 5 do retry end; i") }
|
672
|
+
assert_equal $__rdl_integer_type, do_tc("i = 0; begin i = i + 1; break if i > 2; end while i < 5; i")
|
673
|
+
assert_equal $__rdl_integer_type, do_tc("i = 0; begin i = i + 1; redo if i > 2; end while i < 5; i")
|
674
|
+
assert_equal $__rdl_integer_type, do_tc("i = 0; begin i = i + 1; next if i > 2; end while i < 5; i")
|
675
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("i = 0; begin i = i + 1; retry if i > 2; end while i < 5; i") }
|
676
|
+
|
677
|
+
# break w/arg, next can't take arg
|
678
|
+
assert_equal @t3n, do_tc("while _any_object do break 3 end", env: @env)
|
679
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("while _any_object do next 3 end", env: @env) }
|
680
|
+
assert_equal @t3n, do_tc("begin break 3 end while _any_object", env: @env)
|
681
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("begin next 3 end while _any_object", env: @env) }
|
682
|
+
end
|
683
|
+
|
684
|
+
def test_for
|
685
|
+
assert_equal $__rdl_fixnum_type, do_tc("for i in 1..5 do end; i")
|
686
|
+
assert_equal tt("1 or 2 or 3 or 4 or 5"), do_tc("for i in [1,2,3,4,5] do end; i")
|
687
|
+
assert_equal tt("Range<Fixnum>"), do_tc("for i in 1..5 do break end", env: @env)
|
688
|
+
assert_equal tt("Range<Fixnum>"), do_tc("for i in 1..5 do next end", env: @env)
|
689
|
+
assert_equal tt("Range<Fixnum>"), do_tc("for i in 1..5 do redo end", env: @env) #infinite loop, ok for typing
|
690
|
+
assert_equal tt("Range<Fixnum> or 3"), do_tc("for i in 1..5 do break 3 end", env: @env)
|
691
|
+
assert_equal @tfs, do_tc("for i in 1..5 do next 'three' end; i", env: @env)
|
692
|
+
end
|
693
|
+
|
694
|
+
def test_return
|
695
|
+
assert self.class.class_eval {
|
696
|
+
type "(Fixnum) -> Fixnum", typecheck_now: true
|
697
|
+
def return_ff(x)
|
698
|
+
return 42
|
699
|
+
end
|
700
|
+
}
|
701
|
+
|
702
|
+
assert_raises(RDL::Typecheck::StaticTypeError) {
|
703
|
+
self.class.class_eval {
|
704
|
+
type "(Fixnum) -> Fixnum", typecheck_now: true
|
705
|
+
def return_ff2(x)
|
706
|
+
return "forty-two"
|
707
|
+
end
|
708
|
+
}
|
709
|
+
}
|
710
|
+
|
711
|
+
assert_equal $__rdl_bot_type, do_tc("return 42", scope: @scopefs)
|
712
|
+
assert_equal $__rdl_bot_type, do_tc("if _any_object then return 42 else return 'forty-two' end", env: @env, scope: @scopefs)
|
713
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("if _any_object then return 42 else return 'forty-two' end", env: @env, scope: @scopef) }
|
714
|
+
assert_equal $__rdl_string_type, do_tc("return 42 if _any_object; 'forty-two'", env: @env, scope: @scopef)
|
715
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("return 'forty-two' if _any_object; 42", env: @env, scope: @scopef) }
|
716
|
+
end
|
717
|
+
|
718
|
+
class E
|
719
|
+
type :f, '() -> %integer'
|
720
|
+
type :f=, '(%integer) -> nil'
|
721
|
+
end
|
722
|
+
|
723
|
+
def test_op_asgn
|
724
|
+
assert $__rdl_integer_type, do_tc("x = 0; x += 1")
|
725
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x += 1") }
|
726
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x = Object.new; x += 1", env: @env) }
|
727
|
+
assert_equal $__rdl_nil_type, do_tc("e = E.new; e.f += 1", env: @env) # return type of f=
|
728
|
+
assert_equal $__rdl_false_type, do_tc("x &= false") # weird
|
729
|
+
end
|
730
|
+
|
731
|
+
def test_and_or_asgn
|
732
|
+
self.class.class_eval {
|
733
|
+
var_type :@f_and_or_asgn, "Fixnum"
|
734
|
+
}
|
735
|
+
assert_equal @t3, do_tc("x ||= 3") # weird
|
736
|
+
assert_equal $__rdl_nil_type, do_tc("x &&= 3") # weirder
|
737
|
+
assert_equal $__rdl_fixnum_type, do_tc("@f_and_or_asgn &&= 4", env: @env)
|
738
|
+
assert_equal @t3, do_tc("x = 3; x ||= 'three'")
|
739
|
+
assert_equal @ts3, do_tc("x = 'three'; x ||= 3")
|
740
|
+
assert_equal $__rdl_nil_type, do_tc("e = E.new; e.f ||= 3", env: @env) # return type of f=
|
741
|
+
assert_equal $__rdl_nil_type, do_tc("e = E.new; e.f &&= 3", env: @env) # return type of f=
|
742
|
+
end
|
743
|
+
|
744
|
+
def test_masgn
|
745
|
+
self.class.class_eval {
|
746
|
+
var_type :@f_masgn, "Array<Fixnum>"
|
747
|
+
}
|
748
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x, y = 3") } # allowed in Ruby but probably has surprising behavior
|
749
|
+
assert_equal tt("Array<Fixnum>"), do_tc("a, b = @f_masgn", env: @env)
|
750
|
+
assert_equal $__rdl_fixnum_type, do_tc("a, b = @f_masgn; a", env: @env)
|
751
|
+
assert_equal $__rdl_fixnum_type, do_tc("a, b = @f_masgn; b", env: @env)
|
752
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("var_type :a, 'String'; a, b = @f_masgn", env: @env) }
|
753
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("a, b = 1, 2, 3") }
|
754
|
+
assert_equal @t3, do_tc("a, b = 3, 'two'; a")
|
755
|
+
assert_equal $__rdl_string_type, do_tc("a, b = 3, 'two'; b")
|
756
|
+
assert_equal @t3, do_tc("a = [3, 'two']; x, y = a; x")
|
757
|
+
assert_equal $__rdl_string_type, do_tc("a = [3, 'two']; x, y = a; y")
|
758
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("a = [3, 'two']; x, y = a; a.length", env: @env) }
|
759
|
+
|
760
|
+
# w/send
|
761
|
+
assert_equal tt("2"), do_tc("e = E.new; e.f, b = 1, 2; b", env: @env)
|
762
|
+
assert_equal $__rdl_fixnum_type, do_tc("e = E.new; e.f, b = @f_masgn; b", env: @env)
|
763
|
+
|
764
|
+
# w/splat
|
765
|
+
assert_equal tt("[1, 2, 3]"), do_tc("*x = [1, 2, 3]")
|
766
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("*x = 1") } # allowed in Ruby, but why would you write this code?
|
767
|
+
|
768
|
+
# w/splat on right
|
769
|
+
assert_equal tt("1"), do_tc("x, *y = [1, 2, 3]; x")
|
770
|
+
assert_equal tt("[2, 3]"), do_tc("x, *y = [1, 2, 3]; y")
|
771
|
+
assert_equal tt("1"), do_tc("x, *y = [1]; x")
|
772
|
+
assert_equal tt("[]"), do_tc("x, *y = [1]; y")
|
773
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x, *y = 1") } # allowed in Ruby, but hard to justify, so RDL error
|
774
|
+
assert_equal $__rdl_fixnum_type, do_tc("x, *y = @f_masgn; x", env: @env)
|
775
|
+
assert_equal tt("Array<Fixnum>"), do_tc("x, *y = @f_masgn; y", env: @env)
|
776
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x, y, *z = [1]") } # works in Ruby, but confusing so RDL reports error
|
777
|
+
|
778
|
+
# w/splat on left
|
779
|
+
assert_equal tt("[1, 2]"), do_tc("*x, y = [1, 2, 3]; x")
|
780
|
+
assert_equal tt("3"), do_tc("*x, y = [1, 2, 3]; y")
|
781
|
+
assert_equal tt("[]"), do_tc("*x, y = [1]; x")
|
782
|
+
assert_equal tt("1"), do_tc("*x, y = [1]; y")
|
783
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("*x, y = 1") } # as above
|
784
|
+
assert_equal tt("Array<Fixnum>"), do_tc("*x, y = @f_masgn; x", env: @env)
|
785
|
+
assert_equal $__rdl_fixnum_type, do_tc("*x, y = @f_masgn; y", env: @env)
|
786
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("*x, y, z = [1]") } # as above
|
787
|
+
|
788
|
+
# w/splat in middle
|
789
|
+
assert_equal tt("1"), do_tc("x, *y, z = [1, 2]; x")
|
790
|
+
assert_equal tt("[]"), do_tc("x, *y, z = [1, 2]; y")
|
791
|
+
assert_equal tt("2"), do_tc("x, *y, z = [1, 2]; z")
|
792
|
+
assert_equal tt("1"), do_tc("x, *y, z = [1, 2, 3, 4]; x")
|
793
|
+
assert_equal tt("[2, 3]"), do_tc("x, *y, z = [1, 2, 3, 4]; y")
|
794
|
+
assert_equal tt("4"), do_tc("x, *y, z = [1, 2, 3, 4]; z")
|
795
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x, *y, z = 1") } # as above
|
796
|
+
assert_equal $__rdl_fixnum_type, do_tc("x, *y, z = @f_masgn; x", env: @env)
|
797
|
+
assert_equal tt("Array<Fixnum>"), do_tc("x, *y, z = @f_masgn; y", env: @env)
|
798
|
+
assert_equal $__rdl_fixnum_type, do_tc("x, *y, z = @f_masgn; z", env: @env)
|
799
|
+
end
|
800
|
+
|
801
|
+
def test_cast
|
802
|
+
assert_equal $__rdl_fixnum_type, do_tc("(1 + 2).type_cast('Fixnum')", env: @env)
|
803
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("1.type_cast('Fixnum', 42)", env: @env) }
|
804
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("1.type_cast(Fixnum)", env: @env) }
|
805
|
+
assert_equal $__rdl_fixnum_type, do_tc("(1 + 2).type_cast('Fixnum', force: true)", env: @env)
|
806
|
+
assert_equal $__rdl_fixnum_type, do_tc("(1 + 2).type_cast('Fixnum', force: false)", env: @env)
|
807
|
+
assert_equal $__rdl_fixnum_type, do_tc("(1 + 2).type_cast('Fixnum', force: :blah)", env: @env)
|
808
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("(1 + 2).type_cast('Fixnum', forc: true)", env: @env) }
|
809
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("(1 + 2).type_cast('Fluffy Bunny')") }
|
810
|
+
end
|
811
|
+
|
812
|
+
def test_rescue_ensure
|
813
|
+
assert_equal @t3, do_tc("begin 3; rescue; 4; end") # rescue clause can never be executed
|
814
|
+
assert_equal @t34, do_tc("begin puts 'foo'; 3; rescue; 4; end", env: @env)
|
815
|
+
assert_equal tt("StandardError or 3"), do_tc("begin puts 'foo'; 3; rescue => e; e; end", env: @env)
|
816
|
+
assert_equal tt("RuntimeError or 3"), do_tc("begin puts 'foo'; 3; rescue RuntimeError => e; e; end", env: @env)
|
817
|
+
assert_equal tt("3"), do_tc("begin puts 'foo'; 3; else; 4; end", env: @env) # parser discards else clause!
|
818
|
+
assert_equal tt("RuntimeError or ArgumentError or 3"), do_tc("begin puts 'foo'; 3; rescue RuntimeError => e; e; rescue ArgumentError => x; x; end", env: @env)
|
819
|
+
assert_equal tt("RuntimeError or ArgumentError or 42 or 3"), do_tc("begin puts 'foo'; 3; rescue RuntimeError => e; e; rescue ArgumentError => x; x; else 42; end", env: @env)
|
820
|
+
assert_equal tt("RuntimeError or ArgumentError or 3"), do_tc("begin puts 'foo'; 3; rescue RuntimeError, ArgumentError => e; e; end", env: @env)
|
821
|
+
assert_equal tt("1 or String"), do_tc("tries = 0; begin puts 'foo'; x = 1; rescue; tries = tries + 1; retry unless tries > 5; x = 'one'; end; x", env: @env)
|
822
|
+
assert_equal @t3, do_tc("begin 3; ensure 4; end", env: @env)
|
823
|
+
assert_equal @t4, do_tc("begin x = 3; ensure x = 4; end; x", env: @env)
|
824
|
+
assert_equal @t5, do_tc("begin puts 'foo'; x = 3; rescue; x = 4; ensure x = 5; end; x", env: @env)
|
825
|
+
assert_equal @t34, do_tc("begin puts 'foo'; 3; rescue; 4; ensure 5; end", env: @env)
|
826
|
+
end
|
827
|
+
|
828
|
+
class SubArray < Array
|
829
|
+
end
|
830
|
+
|
831
|
+
class SubHash < Hash
|
832
|
+
end
|
833
|
+
|
834
|
+
def test_array_splat
|
835
|
+
self.class.class_eval {
|
836
|
+
type :_splataf, "() -> Array<Fixnum>"
|
837
|
+
type :_splatas, "() -> Array<String>"
|
838
|
+
type :_splathsf, "() -> Hash<Symbol, Fixnum>"
|
839
|
+
}
|
840
|
+
assert_equal tt("[1]"), do_tc("x = *1")
|
841
|
+
assert_equal tt("[1, 2, 3]"), do_tc("x = [1, *2, 3]")
|
842
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x = [1, *Object.new, 3]", env: @env) } # the Object might or might not be an array...
|
843
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x = [1, *SubArray.new, 3]", env: @env) } # the SubArray is an Array, but unclear how to splat
|
844
|
+
assert_equal tt("[1]"), do_tc("x = *[1]")
|
845
|
+
assert_equal tt("[1, 2, 3]"), do_tc("x = *[1, 2, 3]")
|
846
|
+
assert_equal tt("[1, 2, 3]"), do_tc("x = [1, *[2], 3]")
|
847
|
+
assert_equal tt("[1, 2, 3, 4]"), do_tc("x = [1, *[2, 3], 4]")
|
848
|
+
assert_equal tt("[1, 2, 3, 4]"), do_tc("x = [1, *[2, *[3]], 4]")
|
849
|
+
assert_equal tt("[1, [2, 3], 4]"), do_tc("x = [1, [2, *[3]], 4]")
|
850
|
+
assert_equal tt("[1, 2, 3, 4]"), do_tc("x = [*[1,2], *[3,4]]")
|
851
|
+
assert_equal tt("[]"), do_tc("x = *nil")
|
852
|
+
assert_equal tt("[1, 2]"), do_tc("x = [1, *nil, 2]")
|
853
|
+
assert_equal tt("[[:a, 1]]"), do_tc("x = *{a: 1}")
|
854
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x = [1, *SubHash.new, 3]", env: @env) } # the SubHash is an Hash, but unclear how to splat
|
855
|
+
assert_equal tt("[[:a, 1], [:b, 2], [:c, 3]]"), do_tc("x = *{a: 1, b: 2, c: 3}")
|
856
|
+
assert_equal tt("[1, [:a, 2], 3]"), do_tc("x = [1, *{a: 2}, 3]")
|
857
|
+
assert_equal tt("[1, 2, 3]"), do_tc("y = [2]; x = [1, *y, 3]; ")
|
858
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("y = [2]; x = [1, *y, 3]; y.length") }
|
859
|
+
assert_equal tt("[1, [:a, 2], 3]"), do_tc("y = {a: 2}; x = [1, *y, 3]")
|
860
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("y = {a: 2}; x = [1, *y, 3]; y.length") }
|
861
|
+
|
862
|
+
assert_equal tt("Array<Fixnum>"), do_tc("x = *_splataf", env: @env)
|
863
|
+
assert_equal tt("Array<Fixnum>"), do_tc("x = [1, *_splataf, 2]", env: @env)
|
864
|
+
assert_equal tt("Array<Fixnum>"), do_tc("x = [*_splataf, *_splataf]", env: @env)
|
865
|
+
assert_equal tt("Array<Fixnum or String>"), do_tc("x = [*_splataf, *_splatas]", env: @env)
|
866
|
+
assert_equal tt("Array<Fixnum or String>"), do_tc("x = [1, *_splataf, 2, *_splatas, 3]", env: @env)
|
867
|
+
assert_equal tt("Array<Fixnum or String or 3.0>"), do_tc("x = [1, *_splataf, 2, *_splatas, 3.0]", env: @env)
|
868
|
+
assert_equal tt("Array<[Symbol, Fixnum]>"), do_tc("x = *_splathsf", env: @env)
|
869
|
+
assert_equal tt("Array<1 or 3 or [Symbol, Fixnum]>"), do_tc("x = [1, *_splathsf, 3]", env: @env)
|
870
|
+
end
|
871
|
+
|
872
|
+
def test_hash_kwsplat
|
873
|
+
self.class.class_eval {
|
874
|
+
type :_kwsplathsf, "() -> Hash<Symbol, Fixnum>"
|
875
|
+
type :_kwsplathos, "() -> Hash<Float, String>"
|
876
|
+
}
|
877
|
+
assert_equal tt("{a: 1, b: 2}"), do_tc("x = {a: 1, **{b: 2}}")
|
878
|
+
assert_equal tt("{a: 1}"), do_tc("x = {a: 1, **{}}")
|
879
|
+
assert_equal tt("{a: 1, b: 2, c: 3}"), do_tc("x = {a: 1, **{b: 2}, c: 3}")
|
880
|
+
assert_equal tt("{a: 1, b: 2, c: 3}"), do_tc("x = {a: 1, **{b: 2}, **{c: 3}}")
|
881
|
+
assert_equal tt("{a: 1, b: 2, c: 3}"), do_tc("x = {a: 1, **{b: 2, c: 3}}")
|
882
|
+
assert_equal tt("{a: 1, b: 2, c: 3}"), do_tc("x = {**{a: 1}, b: 2, **{c: 3}}")
|
883
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x = {a: 1, **Object.new}", env: @env) } # may or may not be hash
|
884
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("x = {a: 1, **SubHash.new}", env: @env) } # is a how, but unclear how to splat
|
885
|
+
assert_raises(RDL::Typecheck::StaticTypeError) { do_tc("y = {b: 2}; x = {a: 1, **y}; y.length") }
|
886
|
+
|
887
|
+
assert_equal tt("Hash<Symbol, Fixnum>"), do_tc("x = {**_kwsplathsf}", env: @env)
|
888
|
+
assert_equal tt("Hash<Symbol or Float, Fixnum or String>"), do_tc("x = {**_kwsplathsf, **_kwsplathos}", env: @env)
|
889
|
+
assert_equal tt("Hash<Symbol, Fixnum>"), do_tc("x = {a: 1, **_kwsplathsf, b: 2}", env: @env)
|
890
|
+
assert_equal tt("Hash<Symbol or String, Fixnum or String>"), do_tc("x = {'a' => 1, **_kwsplathsf, b: 'two'}", env: @env)
|
891
|
+
end
|
892
|
+
|
893
|
+
end
|