rdl 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.travis.yml +7 -6
  4. data/CHANGES.md +29 -0
  5. data/README.md +94 -26
  6. data/lib/rdl/boot.rb +82 -41
  7. data/lib/rdl/boot_rails.rb +5 -0
  8. data/lib/rdl/config.rb +9 -1
  9. data/lib/rdl/query.rb +2 -2
  10. data/lib/rdl/typecheck.rb +972 -225
  11. data/lib/rdl/types/annotated_arg.rb +8 -0
  12. data/lib/rdl/types/ast_node.rb +73 -0
  13. data/lib/rdl/types/bot.rb +8 -0
  14. data/lib/rdl/types/bound_arg.rb +63 -0
  15. data/lib/rdl/types/computed.rb +48 -0
  16. data/lib/rdl/types/dependent_arg.rb +9 -0
  17. data/lib/rdl/types/dynamic.rb +61 -0
  18. data/lib/rdl/types/finite_hash.rb +54 -9
  19. data/lib/rdl/types/generic.rb +33 -0
  20. data/lib/rdl/types/intersection.rb +8 -0
  21. data/lib/rdl/types/lexer.rex +6 -1
  22. data/lib/rdl/types/lexer.rex.rb +13 -1
  23. data/lib/rdl/types/method.rb +14 -0
  24. data/lib/rdl/types/nominal.rb +8 -0
  25. data/lib/rdl/types/non_null.rb +8 -0
  26. data/lib/rdl/types/optional.rb +8 -0
  27. data/lib/rdl/types/parser.racc +31 -5
  28. data/lib/rdl/types/parser.tab.rb +540 -302
  29. data/lib/rdl/types/rdl_types.rb +45 -0
  30. data/lib/rdl/types/singleton.rb +14 -1
  31. data/lib/rdl/types/string.rb +104 -0
  32. data/lib/rdl/types/structural.rb +8 -0
  33. data/lib/rdl/types/top.rb +8 -0
  34. data/lib/rdl/types/tuple.rb +32 -8
  35. data/lib/rdl/types/type.rb +54 -11
  36. data/lib/rdl/types/union.rb +41 -2
  37. data/lib/rdl/types/var.rb +10 -0
  38. data/lib/rdl/types/vararg.rb +8 -0
  39. data/lib/rdl/util.rb +13 -10
  40. data/lib/rdl/wrap.rb +271 -27
  41. data/lib/rdl_disable.rb +16 -2
  42. data/lib/types/active_record.rb +1 -0
  43. data/lib/types/core/array.rb +442 -23
  44. data/lib/types/core/basic_object.rb +3 -3
  45. data/lib/types/core/bigdecimal.rb +5 -0
  46. data/lib/types/core/class.rb +2 -0
  47. data/lib/types/core/dir.rb +3 -3
  48. data/lib/types/core/enumerable.rb +4 -4
  49. data/lib/types/core/enumerator.rb +1 -1
  50. data/lib/types/core/file.rb +4 -4
  51. data/lib/types/core/float.rb +203 -0
  52. data/lib/types/core/hash.rb +390 -15
  53. data/lib/types/core/integer.rb +223 -10
  54. data/lib/types/core/io.rb +2 -2
  55. data/lib/types/core/kernel.rb +8 -5
  56. data/lib/types/core/marshal.rb +3 -0
  57. data/lib/types/core/module.rb +3 -3
  58. data/lib/types/core/numeric.rb +0 -2
  59. data/lib/types/core/object.rb +5 -5
  60. data/lib/types/core/pathname.rb +2 -2
  61. data/lib/types/core/process.rb +1 -3
  62. data/lib/types/core/range.rb +1 -1
  63. data/lib/types/core/regexp.rb +2 -2
  64. data/lib/types/core/set.rb +1 -1
  65. data/lib/types/core/string.rb +408 -16
  66. data/lib/types/core/symbol.rb +3 -3
  67. data/lib/types/core/time.rb +1 -1
  68. data/lib/types/core/uri.rb +13 -13
  69. data/lib/types/rails/_helpers.rb +7 -1
  70. data/lib/types/rails/action_controller/mime_responds.rb +2 -0
  71. data/lib/types/rails/active_record/associations.rb +42 -30
  72. data/lib/types/rails/active_record/comp_types.rb +637 -0
  73. data/lib/types/rails/active_record/finder_methods.rb +1 -1
  74. data/lib/types/rails/active_record/model_schema.rb +28 -16
  75. data/lib/types/rails/active_record/relation.rb +5 -3
  76. data/lib/types/rails/active_record/sql-strings.rb +166 -0
  77. data/lib/types/rails/string.rb +1 -1
  78. data/lib/types/sequel.rb +1 -0
  79. data/lib/types/sequel/comp_types.rb +581 -0
  80. data/rdl.gemspec +5 -4
  81. data/test/test_alias.rb +4 -0
  82. data/test/test_array_types.rb +244 -0
  83. data/test/test_bound_types.rb +80 -0
  84. data/test/test_contract.rb +4 -0
  85. data/test/test_dsl.rb +5 -0
  86. data/test/test_dyn_comptype_checks.rb +206 -0
  87. data/test/test_generic.rb +21 -20
  88. data/test/test_hash_types.rb +322 -0
  89. data/test/test_intersection.rb +1 -0
  90. data/test/test_le.rb +29 -4
  91. data/test/test_member.rb +3 -1
  92. data/test/test_parser.rb +5 -0
  93. data/test/test_query.rb +1 -0
  94. data/test/test_rdl.rb +63 -28
  95. data/test/test_rdl_type.rb +4 -0
  96. data/test/test_string_types.rb +102 -0
  97. data/test/test_type_contract.rb +59 -37
  98. data/test/test_typecheck.rb +480 -75
  99. data/test/test_types.rb +17 -0
  100. data/test/test_wrap.rb +5 -0
  101. metadata +35 -5
  102. data/lib/types/rails/active_record/schema_types.rb +0 -51
@@ -4,19 +4,20 @@
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'rdl'
7
- s.version = '2.1.0'
8
- s.date = '2017-06-14'
7
+ s.version = '2.2.0'
8
+ s.date = '2019-06-09'
9
9
  s.summary = 'Ruby type and contract system'
10
10
  s.description = <<-EOF
11
11
  RDL is a gem that adds types and contracts to Ruby. RDL includes extensive
12
12
  support for specifying method types, which can either be enforced as
13
13
  contracts or statically checked.
14
14
  EOF
15
- s.authors = ['Jeffrey S. Foster', 'Brianna M. Ren', 'T. Stephen Strickland', 'Alexander T. Yu', 'Milod Kazerounian']
15
+ s.authors = ['Jeffrey S. Foster', 'Brianna M. Ren', 'T. Stephen Strickland', 'Alexander T. Yu', 'Milod Kazerounian', 'Sankha Narayan Guria']
16
16
  s.email = ['rdl-users@googlegroups.com']
17
17
  s.files = `git ls-files`.split($/)
18
18
  s.executables << 'rdl_query'
19
- s.homepage = 'https://github.com/plum-umd/rdl'
19
+ s.homepage = 'https://github.com/tupl-tufts/rdl'
20
20
  s.license = 'BSD-3-Clause'
21
21
  s.add_runtime_dependency 'parser', '~>2.3', '>= 2.3.1.4'
22
+ s.add_runtime_dependency 'sql-parser', '~>0.0.2'
22
23
  end
@@ -5,6 +5,10 @@ require 'rdl'
5
5
  class TestAlias < Minitest::Test
6
6
  extend RDL::Annotate
7
7
 
8
+ def setup
9
+ RDL.reset
10
+ end
11
+
8
12
  def test_alias_lookup
9
13
  self.class.class_eval {
10
14
  rdl_alias :foobar1, :foobar
@@ -0,0 +1,244 @@
1
+ require 'minitest/autorun'
2
+ $LOAD_PATH << File.dirname(__FILE__) + "/../lib"
3
+ require 'rdl'
4
+ require 'types/core'
5
+
6
+ class TestArrayTypes < Minitest::Test
7
+ extend RDL::Annotate
8
+
9
+ def setup
10
+ RDL.reset
11
+ RDL.readd_comp_types
12
+ RDL.type_params :Array, [:t], :all? unless RDL::Globals.type_params["Array"]
13
+ RDL.type_params(:Range, [:t], nil, variance: [:+]) { |t| t.member?(self.begin) && t.member?(self.end) } unless RDL::Globals.type_params["Range"]
14
+ end
15
+
16
+ def test_array_methods
17
+ self.class.class_eval {
18
+ type '() -> 2', typecheck: :now
19
+ def access_test1()
20
+ x = [1, 2, 3]
21
+ x[1]
22
+ end
23
+
24
+ type '(Array<Integer>) -> Integer', typecheck: :now
25
+ def access_test2(x)
26
+ x[5]
27
+ end
28
+
29
+ type '([2, String, Float], Integer) -> Integer or String or Float', typecheck: :now
30
+ def access_test3(x, y)
31
+ x[y]
32
+ end
33
+
34
+ type '(Array) -> t', typecheck: :now
35
+ def access_test4(a)
36
+ a[3]
37
+ end
38
+
39
+ type '([1,2,3]) -> Array<3 or 2 or 1>', typecheck: :now
40
+ def access_test5(a)
41
+ a[1..4]
42
+ end
43
+
44
+ type '(Array<Integer>) -> Array<Integer>', typecheck: :now
45
+ def access_test6(a)
46
+ a[1..4]
47
+ end
48
+
49
+ type '([1,2,3]) -> [2,3]', typecheck: :now
50
+ def access_test7(a)
51
+ a[1, 9]
52
+ end
53
+
54
+ type '([1,2,3]) -> 2', typecheck: :now
55
+ def fetch_test1(a)
56
+ a[1]
57
+ end
58
+
59
+ type '([1,2,3]) -> 1', typecheck: :now
60
+ def first_test1(a)
61
+ a.first
62
+ end
63
+
64
+ type '([1,2,3], Integer) -> Array<3 or 2 or 1>', typecheck: :now
65
+ def first_test2(a, i)
66
+ a.first(i)
67
+ end
68
+
69
+ type '() -> [1,2,3,1,2,3]', typecheck: :now
70
+ def mult_test1
71
+ [1,2,3]*2
72
+ end
73
+
74
+ type '([1,2,3], Integer) -> Array<3 or 2 or 1>', typecheck: :now
75
+ def mult_test2(a, i)
76
+ a * i
77
+ end
78
+
79
+ type '([1,2,3]) -> 3', typecheck: :now
80
+ def count_test1(a)
81
+ a.count
82
+ end
83
+
84
+ type '(Array<Integer>) -> Integer', typecheck: :now
85
+ def count_test2(a)
86
+ a.count
87
+ end
88
+
89
+ type '([1,2,3]) -> [1,2,3,4]', typecheck: :now
90
+ def append_test1(a)
91
+ a << 4
92
+ end
93
+
94
+ type '(Array<Integer>) -> Array<Integer>', typecheck: :now
95
+ def append_test2(a)
96
+ a << 5
97
+ end
98
+
99
+ type '([1,2,3]) -> [1,2,3,4,5]', typecheck: :now
100
+ def push_test1(a)
101
+ a.push(4, 5)
102
+ end
103
+
104
+ type :append_callee, '([1,2,3]) -> %bool'
105
+
106
+ type '([1,2,3]) -> %bool', typecheck: :append_fail1
107
+ def append_fail_test1(a)
108
+ append_callee(a)
109
+ a << 4
110
+ true
111
+ end
112
+
113
+ type '([1,2,3], [4,5,String]) -> [1,2,3,4,5,String]', typecheck: :now
114
+ def plus_test1(x, y)
115
+ x+y
116
+ end
117
+
118
+ type '([Integer,Integer,Integer], Array<String>) -> Array<Integer or String>', typecheck: :now
119
+ def plus_test2(x, y)
120
+ x+y
121
+ end
122
+
123
+ type '([1,2,3], Array) -> Array', typecheck: :now
124
+ def plus_test3(x, y)
125
+ x + y
126
+ end
127
+
128
+ type '(Array<String>, Array) -> Array', typecheck: :now
129
+ def plus_test4(x, y)
130
+ x + y
131
+ end
132
+
133
+ type '([1,2,3]) -> true', typecheck: :now
134
+ def include_test1(x)
135
+ x.include?(1)
136
+ end
137
+
138
+ type '([1,2,Integer]) -> %bool', typecheck: :now
139
+ def include_test2(x)
140
+ x.include?(4)
141
+ end
142
+
143
+ type '(Array<Integer>) -> %bool', typecheck: :now
144
+ def include_test3(x)
145
+ x.include?(42)
146
+ end
147
+
148
+ type '([1,2,3]) -> 2', typecheck: :now
149
+ def slice_test1(x)
150
+ x.slice(1)
151
+ end
152
+
153
+ type '([1,2,3]) -> [2,3]', typecheck: :now
154
+ def slice_test2(x)
155
+ x.slice(1,2)
156
+ end
157
+
158
+ type '([1,2,3]) -> [1,4 or 2,3]', typecheck: :now
159
+ def assign_test1(x)
160
+ x[1] = 4
161
+ x
162
+ end
163
+
164
+ type '(Integer, [1,2,3]) -> Array<1 or 2 or 3 or String>', typecheck: :now
165
+ def assign_test2(i, x)
166
+ x[i] = "hi"
167
+ x
168
+ end
169
+
170
+ type '(Array<Integer>) -> Array<Integer>', typecheck: :now
171
+ def assign_test3(x)
172
+ x[1] = 2
173
+ x
174
+ end
175
+
176
+ type :assign_callee, '([1,2,3]) -> %bool'
177
+
178
+ type '([1,2,3]) -> 2', typecheck: :now
179
+ def assign_test4(x)
180
+ assign_callee(x)
181
+ x[1] = 2
182
+ end
183
+
184
+ type '([1,2,3]) -> %any', typecheck: :assign_fail1
185
+ def assign_fail_test1(x)
186
+ assign_callee
187
+ x[1] = 100
188
+ end
189
+
190
+ type '(Array<Integer>) -> %any', typecheck: :assign_fail2
191
+ def assign_fail_test2(x)
192
+ x[1] = "hi"
193
+ end
194
+
195
+ type '([1,2,3]) -> false', typecheck: :now
196
+ def empty_test1(x)
197
+ x.empty?
198
+ end
199
+
200
+ type '(Array<Integer>) -> %bool', typecheck: :now
201
+ def empty_test2(x)
202
+ x.empty?
203
+ end
204
+
205
+ type '([1,2,3]) -> 1', typecheck: :now
206
+ def index_test1(x)
207
+ x.index(2)
208
+ end
209
+
210
+ type '([1,2,3], Integer) -> Integer', typecheck: :now
211
+ def index_test2(x, y)
212
+ x.index(y)
213
+ end
214
+
215
+ type '([1,Integer,3], 2) -> Integer', typecheck: :now
216
+ def index_test3(x, y)
217
+ x.index(y)
218
+ end
219
+
220
+ type '([1,2,3]) -> [3,2,1]', typecheck: :now
221
+ def reverse_test1(x)
222
+ x.reverse
223
+ end
224
+
225
+ type '([1,2,3]) -> [1,2,3]', typecheck: :now
226
+ def reverse_test2(x)
227
+ x.reverse
228
+ x
229
+ end
230
+
231
+ type '([1,2,3]) -> [3 or 1,2,1 or 3]', typecheck: :now
232
+ def reverse_test3(x)
233
+ x.reverse!
234
+ x
235
+ end
236
+ }
237
+
238
+ assert_raises(RDL::Typecheck::StaticTypeError) { RDL.do_typecheck :append_fail1 }
239
+ assert_raises(RDL::Typecheck::StaticTypeError) { RDL.do_typecheck :assign_fail1 }
240
+ assert_raises(RDL::Typecheck::StaticTypeError) { RDL.do_typecheck :assign_fail2 }
241
+ end
242
+
243
+ end
244
+
@@ -0,0 +1,80 @@
1
+ require 'minitest/autorun'
2
+ $LOAD_PATH << File.dirname(__FILE__) + "/../lib"
3
+ require 'rdl'
4
+ require 'types/core'
5
+
6
+
7
+ class TestBoundTypes < Minitest::Test
8
+ extend RDL::Annotate
9
+
10
+ def test_bound_types
11
+ self.class.class_eval {
12
+ type :uses_bound, "(t<::Integer) -> ``if t.is_a?(RDL::Type::SingletonType) then RDL::Globals.types[:integer] else RDL::Globals.types[:string] end``"
13
+
14
+ type :uses_bound_twice, "(t<::Integer, p<::Integer) -> ``if t==p then RDL::Globals.types[:integer] else RDL::Globals.types[:string] end``"
15
+
16
+ type :uses_optional, "(?String, t<::Integer) -> ``if t.is_a?(RDL::Type::SingletonType) then RDL::Globals.types[:integer] else RDL::Globals.types[:string] end``"
17
+
18
+ type "(Integer) -> String", typecheck: :now
19
+ def calls_bound1(x)
20
+ uses_bound(x)
21
+ end
22
+
23
+ type "(1) -> Integer", typecheck: :now
24
+ def calls_bound2(x)
25
+ uses_bound(x)
26
+ end
27
+
28
+ type "(Integer) -> Integer", typecheck: :fail1
29
+ def calls_bound3(x)
30
+ uses_bound(x)
31
+ end
32
+
33
+ type "(1) -> String", typecheck: :fail2
34
+ def calls_bound4(x)
35
+ uses_bound(x)
36
+ end
37
+
38
+ type "(1, 1) -> Integer", typecheck: :now
39
+ def calls_bound5(x, y)
40
+ uses_bound_twice(x, y)
41
+ end
42
+
43
+ type "(1, 2) -> String", typecheck: :now
44
+ def calls_bound6(x, y)
45
+ uses_bound_twice(x, y)
46
+ end
47
+
48
+ type "(1, 2) -> Integer", typecheck: :fail3
49
+ def calls_bound7(x, y)
50
+ uses_bound_twice(x, y)
51
+ end
52
+
53
+ type "(1) -> Integer", typecheck: :now
54
+ def calls_bound8(x)
55
+ uses_optional(x)
56
+ end
57
+
58
+ type "(1) -> Integer", typecheck: :now
59
+ def calls_bound9(x)
60
+ uses_optional('x', x)
61
+ end
62
+
63
+ type "(1) -> String", typecheck: :fail4
64
+ def calls_bound10(x)
65
+ uses_optional('x', x)
66
+ end
67
+
68
+ type "(1) -> String", typecheck: :fail5
69
+ def calls_bound11(x)
70
+ uses_optional(x)
71
+ end
72
+ }
73
+ assert_raises(RDL::Typecheck::StaticTypeError) { RDL.do_typecheck :fail1 }
74
+ assert_raises(RDL::Typecheck::StaticTypeError) { RDL.do_typecheck :fail2 }
75
+ assert_raises(RDL::Typecheck::StaticTypeError) { RDL.do_typecheck :fail3 }
76
+ assert_raises(RDL::Typecheck::StaticTypeError) { RDL.do_typecheck :fail4 }
77
+ assert_raises(RDL::Typecheck::StaticTypeError) { RDL.do_typecheck :fail5 }
78
+ end
79
+
80
+ end
@@ -5,6 +5,10 @@ require 'rdl'
5
5
  class TestContract < Minitest::Test
6
6
  include RDL::Contract
7
7
 
8
+ def setup
9
+ RDL.reset
10
+ end
11
+
8
12
  def test_flat
9
13
  pos = FlatContract.new("Positive") { |x| x > 0 }
10
14
  assert_equal "Positive", pos.to_s
@@ -4,6 +4,11 @@ require 'rdl'
4
4
 
5
5
  class TestDsl < Minitest::Test
6
6
 
7
+ def setup
8
+ RDL.reset
9
+ end
10
+
11
+
7
12
  class Pair
8
13
 
9
14
  # dsl {
@@ -0,0 +1,206 @@
1
+ require 'minitest/autorun'
2
+ $LOAD_PATH << File.dirname(__FILE__) + "/../lib"
3
+ require 'rdl'
4
+ require 'types/core'
5
+
6
+ class TestDynChecks < Minitest::Test
7
+ extend RDL::Annotate
8
+
9
+ RDL::Config.instance.check_comp_types = true
10
+ RDL::Config.instance.rerun_comp_types = true
11
+
12
+ type :bar1, "(Integer) -> ``RDL::Type::SingletonType.new(2)``", wrap: false
13
+
14
+ type "(Integer) -> Integer", typecheck: :now, wrap: false
15
+ def foo1(x)
16
+ bar1(x)
17
+ end
18
+
19
+ ## First, a silly example. `bar1` (defined below) always returns 1, but its comp type says it always returns 2.
20
+ ## `foo1` will type check properly, but the `bar1` error won't be caught until `foo` is called after type checking.
21
+ def test_foo1_fail
22
+ RDL::Util.silent_warnings { self.class.class_eval("def bar1(x) 1; end") }
23
+ assert_raises(RDL::Type::TypeError) { self.class.new(nil).foo1(1) }
24
+ end
25
+
26
+ ## If we redefine `bar1`, it should work.
27
+
28
+ def test_foo1_pass
29
+ RDL::Util.silent_warnings { self.class.class_eval("def bar1(x) 2; end") }
30
+ assert self.class.new(nil).foo1(1)
31
+ end
32
+
33
+
34
+ ## Let's try again, with arrays.
35
+
36
+ type :return_array, "() -> ``RDL::Type::TupleType.new(RDL::Type::SingletonType.new(0), RDL::Type::SingletonType.new(0), RDL::Type::SingletonType.new(0))``", wrap: false
37
+
38
+ type "() -> Integer", typecheck: :now ## this type check should pass
39
+ def calls_array
40
+ a = return_array
41
+ a[1]
42
+ end
43
+
44
+ def test_array_fail
45
+ RDL::Util.silent_warnings{ self.class.class_eval("def return_array() [1,2,3]; end") }
46
+ assert_raises(RDL::Type::TypeError) { self.class.new(nil).calls_array }
47
+ end
48
+
49
+ def test_array_pass
50
+ RDL::Util.silent_warnings { self.class.class_eval("def return_array() [0,0,0]; end") }
51
+ assert self.class.new(nil).calls_array
52
+ end
53
+
54
+ # Now for a slightly-but-not-really more realistic example, with a mock (very small) DB schema.
55
+
56
+ class People
57
+ extend RDL::Annotate
58
+ @people_schema = RDL::Globals.parser.scan_str "#T { name: String, age: Integer }"
59
+ type 'self.where', "(``raise 'Expected schema' unless @people_schema; @people_schema``) -> Integer", wrap: false
60
+ def self.where(record)
61
+ 1 ## not actually looking anything up, so just return a dummy int
62
+ end
63
+
64
+ type :person_to_look_up, '() -> {name: String, age: 30}', wrap: false
65
+
66
+ type "() -> Integer", wrap: false, typecheck: :now ## type checking will succeed the first time
67
+ def calls_where
68
+ self.class.where(person_to_look_up)
69
+ end
70
+
71
+
72
+ end
73
+
74
+ def test_where_fail
75
+ RDL::Util.silent_warnings{ People.class_eval("def person_to_look_up() {name: 'alice', age: '30'}; end") }
76
+ assert_raises(RDL::Type::TypeError) { People.new.calls_where }
77
+ end
78
+
79
+ def test_where_pass
80
+ RDL::Util.silent_warnings { People.class_eval("def person_to_look_up() {name: 'alice', age: 30}; end") }
81
+ assert People.new.calls_where
82
+ end
83
+
84
+
85
+ # A test where the same method returns different types in different calls:
86
+
87
+ def self.called_thrice_output(trec, targs)
88
+ if targs[0].is_a?(RDL::Type::NominalType)
89
+ RDL::Globals.types[:integer]
90
+ elsif targs[0].is_a?(RDL::Type::SingletonType)
91
+ RDL::Type::SingletonType.new(targs[0].val + 1)
92
+ end
93
+ end
94
+
95
+ type :called_thrice, "(Integer) -> ``called_thrice_output(trec, targs)``", wrap: false
96
+
97
+
98
+ type "(Integer) -> Integer", wrap: false, typecheck: :now
99
+ def multi_caller(x)
100
+ called_thrice(x) ## should have type Integer
101
+ called_thrice(1) ## Should have type 2
102
+ called_thrice(2) ## Should have type 3
103
+ end
104
+
105
+ def test_multi_pass
106
+ RDL::Util.silent_warnings { self.class.class_eval "def called_thrice(x) x+1; end" } ## this will satisfy all call return types
107
+ assert self.class.new(nil).multi_caller(0)
108
+ end
109
+
110
+ def test_multi_fail
111
+ RDL::Util.silent_warnings { self.class.class_eval "def called_thrice(x) if (x==2) then x+2 else x+1 end; end" } ## silly
112
+ assert_raises(RDL::Type::TypeError) { multi_caller(0) }
113
+ end
114
+
115
+
116
+ # Now to test op_asgn.
117
+
118
+ type "(Integer) -> Integer", typecheck: :now, wrap: false
119
+ def op_asgn_test(x)
120
+ x += 1
121
+ end
122
+
123
+ def test_op_asgn
124
+ assert self.class.new(nil).op_asgn_test(1)
125
+ assert_raises(RDL::Type::TypeError) { self.class.new(nil).op_asgn_test(1.5) } ## Because `op_asgn_test` isn't wrapped, this should only raise error once :+ is called
126
+ end
127
+
128
+ type "([1,2,3]) -> Integer", typecheck: :now, wrap: false
129
+ def op_asgn_arr(arr)
130
+ arr[1] += 1
131
+ end
132
+
133
+ def test_op_asgn_arr
134
+ assert self.class.new(nil).op_asgn_arr([1,2,3])
135
+ assert_raises(RDL::Type::TypeError) { self.class.new(nil).op_asgn_arr([1,42, 3]) } ## same issue as above
136
+ end
137
+
138
+
139
+ # Now, we'll test the re-running of computed types; this has been tested in all the examples above, but here we'll test that it fails correctly.
140
+
141
+ class CompFail
142
+ extend RDL::Annotate
143
+ #@@compfail = 1
144
+ =begin
145
+ def self.get_val()
146
+ @@compfail
147
+ end
148
+
149
+ def self.set_val(v)
150
+ @@compfail = v
151
+ end
152
+
153
+ type "(``if (get_val == 1) then RDL::Globals.types[:integer] else RDL::Type::UnionType.new(RDL::Globals.types[:integer], RDL::Globals.types[:string]) end``) -> Integer", wrap: false ## pathological type depending on @@compfail
154
+ def bar(x)
155
+ x
156
+ end
157
+
158
+ type "(Integer) -> Integer", typecheck: :now, wrap: false ## will type check fine
159
+ def foo(x)
160
+ bar(x)
161
+ end
162
+ =end
163
+ end
164
+
165
+ def test_rerun_comp_type
166
+ CompFail.class_eval {
167
+ #RDL::Config.instance.check_comp_types = true
168
+ #RDL::Config.instance.rerun_comp_types = true
169
+
170
+ @@compfail = 1
171
+ def self.get_val()
172
+ @@compfail
173
+ end
174
+
175
+ def self.set_val(v)
176
+ @@compfail = v
177
+ end
178
+
179
+ type "(``if (get_val == 1) then RDL::Globals.types[:integer] else RDL::Type::UnionType.new(RDL::Globals.types[:integer], RDL::Globals.types[:string]) end``) -> Integer", wrap: false ## pathological type depending on @@compfail
180
+ def bar(x)
181
+ x
182
+ end
183
+
184
+ RDL::Config.instance.check_comp_types = true
185
+ RDL::Config.instance.rerun_comp_types = true
186
+
187
+ type "(Integer) -> Integer", typecheck: :now, wrap: false ## will type check fine
188
+ def foo2(x)
189
+ bar(x)
190
+ end
191
+ }
192
+
193
+ ## These are needed out here too due to weird orderings involving RDL.reset.
194
+ assert CompFail.new.foo2(1) ## will run fine
195
+ CompFail.set_val(2) ## change heap
196
+ assert_raises(RDL::Type::TypeError) { CompFail.new.foo2(1) }
197
+
198
+ RDL::Config.instance.check_comp_types = false
199
+ RDL::Config.instance.rerun_comp_types = false
200
+ end
201
+
202
+ RDL::Config.instance.check_comp_types = false
203
+ RDL::Config.instance.rerun_comp_types = false
204
+
205
+
206
+ end