typed.rb 0.0.11

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 (173) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +26 -0
  3. data/bin/typed.rb +110 -0
  4. data/lib/typed/language.rb +131 -0
  5. data/lib/typed/model/tm_abs.rb +104 -0
  6. data/lib/typed/model/tm_array_literal.rb +25 -0
  7. data/lib/typed/model/tm_boolean.rb +15 -0
  8. data/lib/typed/model/tm_boolean_operator.rb +34 -0
  9. data/lib/typed/model/tm_break.rb +24 -0
  10. data/lib/typed/model/tm_case_when.rb +38 -0
  11. data/lib/typed/model/tm_class.rb +63 -0
  12. data/lib/typed/model/tm_const.rb +29 -0
  13. data/lib/typed/model/tm_defined.rb +19 -0
  14. data/lib/typed/model/tm_error.rb +16 -0
  15. data/lib/typed/model/tm_float.rb +15 -0
  16. data/lib/typed/model/tm_for.rb +42 -0
  17. data/lib/typed/model/tm_fun.rb +165 -0
  18. data/lib/typed/model/tm_global_var.rb +22 -0
  19. data/lib/typed/model/tm_global_var_assignment.rb +20 -0
  20. data/lib/typed/model/tm_hash_literal.rb +32 -0
  21. data/lib/typed/model/tm_if_else.rb +24 -0
  22. data/lib/typed/model/tm_instance_var.rb +23 -0
  23. data/lib/typed/model/tm_instance_var_assignment.rb +32 -0
  24. data/lib/typed/model/tm_int.rb +15 -0
  25. data/lib/typed/model/tm_local_var_asgn.rb +35 -0
  26. data/lib/typed/model/tm_mass_asgn.rb +60 -0
  27. data/lib/typed/model/tm_mlhs.rb +87 -0
  28. data/lib/typed/model/tm_module.rb +51 -0
  29. data/lib/typed/model/tm_next.rb +24 -0
  30. data/lib/typed/model/tm_nil.rb +14 -0
  31. data/lib/typed/model/tm_range_literal.rb +30 -0
  32. data/lib/typed/model/tm_regexp.rb +27 -0
  33. data/lib/typed/model/tm_rescue.rb +27 -0
  34. data/lib/typed/model/tm_return.rb +24 -0
  35. data/lib/typed/model/tm_s_class.rb +30 -0
  36. data/lib/typed/model/tm_self.rb +22 -0
  37. data/lib/typed/model/tm_send.rb +300 -0
  38. data/lib/typed/model/tm_sequencing.rb +53 -0
  39. data/lib/typed/model/tm_string.rb +15 -0
  40. data/lib/typed/model/tm_string_interpolation.rb +21 -0
  41. data/lib/typed/model/tm_super.rb +27 -0
  42. data/lib/typed/model/tm_symbol.rb +15 -0
  43. data/lib/typed/model/tm_symbol_interpolation.rb +21 -0
  44. data/lib/typed/model/tm_try.rb +29 -0
  45. data/lib/typed/model/tm_var.rb +28 -0
  46. data/lib/typed/model/tm_while.rb +43 -0
  47. data/lib/typed/model.rb +48 -0
  48. data/lib/typed/prelude.rb +939 -0
  49. data/lib/typed/prelude_existential_registry.bin +0 -0
  50. data/lib/typed/prelude_generic_registry.bin +0 -0
  51. data/lib/typed/prelude_registry.bin +0 -0
  52. data/lib/typed/runtime/ast_parser.rb +589 -0
  53. data/lib/typed/runtime/method_signature_processor.rb +72 -0
  54. data/lib/typed/runtime/normalization/validations.rb +47 -0
  55. data/lib/typed/runtime/normalization.rb +196 -0
  56. data/lib/typed/runtime/parser_context.rb +36 -0
  57. data/lib/typed/runtime/type_parser.rb +215 -0
  58. data/lib/typed/runtime/type_registry.rb +170 -0
  59. data/lib/typed/runtime/type_signature_processor.rb +34 -0
  60. data/lib/typed/runtime.rb +33 -0
  61. data/lib/typed/type_signature/parser.rb +240 -0
  62. data/lib/typed/types/polymorphism/existential_type_variable.rb +13 -0
  63. data/lib/typed/types/polymorphism/generic_comparisons.rb +134 -0
  64. data/lib/typed/types/polymorphism/generic_variables.rb +24 -0
  65. data/lib/typed/types/polymorphism/type_variable.rb +138 -0
  66. data/lib/typed/types/polymorphism/type_variable_register.rb +298 -0
  67. data/lib/typed/types/polymorphism/unification.rb +579 -0
  68. data/lib/typed/types/ty_boolean.rb +15 -0
  69. data/lib/typed/types/ty_dynamic.rb +39 -0
  70. data/lib/typed/types/ty_either.rb +168 -0
  71. data/lib/typed/types/ty_error.rb +18 -0
  72. data/lib/typed/types/ty_existential_type.rb +22 -0
  73. data/lib/typed/types/ty_function.rb +144 -0
  74. data/lib/typed/types/ty_generic_function.rb +115 -0
  75. data/lib/typed/types/ty_generic_object.rb +180 -0
  76. data/lib/typed/types/ty_generic_singleton_object.rb +238 -0
  77. data/lib/typed/types/ty_object.rb +256 -0
  78. data/lib/typed/types/ty_singleton_object.rb +78 -0
  79. data/lib/typed/types/ty_stack_jump.rb +44 -0
  80. data/lib/typed/types/ty_top_level_object.rb +38 -0
  81. data/lib/typed/types.rb +60 -0
  82. data/lib/typed/typing_context.rb +206 -0
  83. data/lib/typed/version.rb +3 -0
  84. data/lib/typed.rb +161 -0
  85. data/spec/lib/ast_parser_spec.rb +101 -0
  86. data/spec/lib/examples/animals.rb +44 -0
  87. data/spec/lib/examples/counter.rb +16 -0
  88. data/spec/lib/examples/if.rb +31 -0
  89. data/spec/lib/language_spec.rb +36 -0
  90. data/spec/lib/model/tm_abs_spec.rb +66 -0
  91. data/spec/lib/model/tm_array_literal_spec.rb +36 -0
  92. data/spec/lib/model/tm_case_when_spec.rb +39 -0
  93. data/spec/lib/model/tm_class_spec.rb +67 -0
  94. data/spec/lib/model/tm_defined_spec.rb +10 -0
  95. data/spec/lib/model/tm_for_spec.rb +150 -0
  96. data/spec/lib/model/tm_fun_spec.rb +11 -0
  97. data/spec/lib/model/tm_hash_literal_spec.rb +40 -0
  98. data/spec/lib/model/tm_mass_asgn_spec.rb +104 -0
  99. data/spec/lib/model/tm_module_spec.rb +42 -0
  100. data/spec/lib/model/tm_regexp_spec.rb +9 -0
  101. data/spec/lib/model/tm_return_spec.rb +47 -0
  102. data/spec/lib/model/tm_s_class_spec.rb +27 -0
  103. data/spec/lib/model/tm_self_spec.rb +19 -0
  104. data/spec/lib/model/tm_string_interpolation_spec.rb +10 -0
  105. data/spec/lib/model/tm_symbol_interpolation_spec.rb +10 -0
  106. data/spec/lib/model/tm_symbol_spec.rb +9 -0
  107. data/spec/lib/model/tm_while_spec.rb +141 -0
  108. data/spec/lib/polymorphism/type_variable_spec.rb +14 -0
  109. data/spec/lib/polymorphism/unification_spec.rb +328 -0
  110. data/spec/lib/prelude/array_spec.rb +263 -0
  111. data/spec/lib/prelude/class_spec.rb +12 -0
  112. data/spec/lib/prelude/enumerable_spec.rb +278 -0
  113. data/spec/lib/prelude/enumerator_spec.rb +101 -0
  114. data/spec/lib/prelude/hash_spec.rb +361 -0
  115. data/spec/lib/prelude/kernel_spec.rb +23 -0
  116. data/spec/lib/prelude/object_spec.rb +22 -0
  117. data/spec/lib/prelude/pair_spec.rb +16 -0
  118. data/spec/lib/prelude/showable_spec.rb +31 -0
  119. data/spec/lib/prelude/string_spec.rb +98 -0
  120. data/spec/lib/runtime/normalization_spec.rb +29 -0
  121. data/spec/lib/runtime/validations_spec.rb +56 -0
  122. data/spec/lib/runtime_spec.rb +503 -0
  123. data/spec/lib/type_signature/parser_spec.rb +239 -0
  124. data/spec/lib/types/comparisons_spec.rb +35 -0
  125. data/spec/lib/types/polymorphism/generic_comparisons_spec.rb +492 -0
  126. data/spec/lib/types/polymorphism/type_variable_register_spec.rb +128 -0
  127. data/spec/lib/types/ty_dynamic_spec.rb +103 -0
  128. data/spec/lib/types/ty_either_spec.rb +288 -0
  129. data/spec/lib/types/ty_error_spec.rb +18 -0
  130. data/spec/lib/types/ty_generic_object_spec.rb +78 -0
  131. data/spec/lib/types/ty_generic_singleton_object_spec.rb +288 -0
  132. data/spec/lib/types/typing_context_spec.rb +86 -0
  133. data/spec/lib/types_spec.rb +174 -0
  134. data/spec/lib/typing/boolean_asgn_spec.rb +134 -0
  135. data/spec/lib/typing/break_spec.rb +79 -0
  136. data/spec/lib/typing/generics_spec.rb +191 -0
  137. data/spec/lib/typing/instance_vars_spec.rb +103 -0
  138. data/spec/lib/typing/next_spec.rb +29 -0
  139. data/spec/lib/typing/op_asgn_spec.rb +104 -0
  140. data/spec/lib/typing/overriden_methods_spec.rb +31 -0
  141. data/spec/lib/typing/subtyping_spec.rb +112 -0
  142. data/spec/lib/typing/tm_boolean_operator_spec.rb +100 -0
  143. data/spec/lib/typing/tm_boolean_spec.rb +61 -0
  144. data/spec/lib/typing/tm_const_spec.rb +28 -0
  145. data/spec/lib/typing/tm_defined_spec.rb +12 -0
  146. data/spec/lib/typing/tm_fun_spec.rb +347 -0
  147. data/spec/lib/typing/tm_global_var_spec.rb +33 -0
  148. data/spec/lib/typing/tm_if_else_spec.rb +104 -0
  149. data/spec/lib/typing/tm_ignore_spec.rb +24 -0
  150. data/spec/lib/typing/tm_instance_vars_spec.rb +117 -0
  151. data/spec/lib/typing/tm_local_var_asgn_spec.rb +134 -0
  152. data/spec/lib/typing/tm_mlhs_spec.rb +164 -0
  153. data/spec/lib/typing/tm_module_spec.rb +89 -0
  154. data/spec/lib/typing/tm_raise_spec.rb +31 -0
  155. data/spec/lib/typing/tm_range_literal_spec.rb +25 -0
  156. data/spec/lib/typing/tm_regexp_spec.rb +14 -0
  157. data/spec/lib/typing/tm_return_spec.rb +45 -0
  158. data/spec/lib/typing/tm_send_casting_spec.rb +26 -0
  159. data/spec/lib/typing/tm_send_class_methods_spec.rb +42 -0
  160. data/spec/lib/typing/tm_send_generic_apply_spec.rb +103 -0
  161. data/spec/lib/typing/tm_send_generic_methods_spec.rb +77 -0
  162. data/spec/lib/typing/tm_send_initialize_spec.rb +68 -0
  163. data/spec/lib/typing/tm_send_lambda_spec.rb +135 -0
  164. data/spec/lib/typing/tm_send_spec.rb +217 -0
  165. data/spec/lib/typing/tm_send_yield_block_spec.rb +308 -0
  166. data/spec/lib/typing/tm_sequencing_spec.rb +174 -0
  167. data/spec/lib/typing/tm_string_interpolation_spec.rb +19 -0
  168. data/spec/lib/typing/tm_super_spec.rb +63 -0
  169. data/spec/lib/typing/tm_symbol_interpolation_spec.rb +19 -0
  170. data/spec/lib/typing/tm_symbol_spec.rb +14 -0
  171. data/spec/lib/typing/tm_try_spec.rb +73 -0
  172. data/spec/spec_helper.rb +140 -0
  173. metadata +216 -0
@@ -0,0 +1,263 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe Array do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ describe '#initialize' do
7
+ it 'type checks / -> Array[T]' do
8
+ result = language.check('Array.(Integer).new')
9
+ expect(result.ruby_type).to eq(Array)
10
+ expect(result.type_vars.first.bound.ruby_type).to eq(Integer)
11
+ end
12
+
13
+ it 'type checks / Integer -> Array[T]' do
14
+ result = language.check('Array.(Integer).new(3)')
15
+ expect(result.ruby_type).to eq(Array)
16
+ expect(result.type_vars.first.bound.ruby_type).to eq(Integer)
17
+ end
18
+
19
+ it 'type checks / Integer -> [T] -> Array[T]' do
20
+ result = language.check('Array.(String).new(3, "start")')
21
+ expect(result.ruby_type).to eq(Array)
22
+ expect(result.type_vars.first.bound.ruby_type).to eq(String)
23
+
24
+ expect {
25
+ result = language.check('Array.(String).new(3, 0)')
26
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
27
+ end
28
+ end
29
+
30
+ describe '#[]' do
31
+ it 'type checks / Object -> Object' do
32
+ result = language.check('Array.(Integer).new(10,0)[0]')
33
+ expect(result.ruby_type).to eq(Object)
34
+ end
35
+
36
+ it 'type checks / Integer -> Integer - Array[T]' do
37
+ result = language.check('Array.(Integer).new(10,0)[0, 3]')
38
+ expect(result.ruby_type).to eq(Array)
39
+ expect(result.type_vars.first.bound.ruby_type).to eq(Integer)
40
+ end
41
+ end
42
+
43
+ describe '#collect[E]' do
44
+ it 'type checks / &([T] -> [E]) -> Array[E]' do
45
+ result = language.check('Array.(Integer).new(10,0).collect{ |e| e.to_s }')
46
+ expect(result.ruby_type).to eq(Array)
47
+ expect(result.type_vars.first.bound.ruby_type).to eq(String)
48
+ end
49
+ end
50
+
51
+ describe '#concat' do
52
+ it 'type checks / Array[T] -> Array[T]' do
53
+ result = language.check('Array.(Integer).new(10,0).concat(Array.(Integer).new(10,0))')
54
+ expect(result.ruby_type).to eq(Array)
55
+ expect(result.type_vars.first.bound.ruby_type).to eq(Integer)
56
+
57
+ expect {
58
+ language.check('Array.(Integer).new(10,0).concat(Array.(String).new(10,"blah"))')
59
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
60
+ end
61
+ end
62
+
63
+ describe '#count' do
64
+ it 'type checks / &([T] -> Boolean) -> Integer' do
65
+ result = language.check('Array.(Integer).new(10,0).count(0)')
66
+ expect(result.ruby_type).to eq(Integer)
67
+
68
+ result = language.check('Array.(Integer).new(10,0).count{ |x| x == 0 }')
69
+ expect(result.ruby_type).to eq(Integer)
70
+
71
+ expect {
72
+ code = <<__CODE
73
+ ts '#testarrs / String -> Boolean'
74
+ def testarrs(s); true; end
75
+
76
+ Array.(Integer).new(10,0).count{ |x| testarrs(x) }
77
+ __CODE
78
+ language.check(code)
79
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
80
+ end
81
+ end
82
+
83
+ describe '#eql?' do
84
+ it 'type checks / Array[?] -> Boolean' do
85
+ code = <<__CODE
86
+ as = Array.(Integer).new(10,0)
87
+ bs = Array.(String).new(10,'')
88
+
89
+ as.eql?(bs)
90
+ __CODE
91
+ result = language.check(code)
92
+ expect(result.ruby_type).to eq(TrueClass)
93
+ end
94
+ end
95
+
96
+ describe '#flatten' do
97
+ it 'type checks / -> Array[Object]' do
98
+ code = <<__END
99
+ a1 = Array.(Integer).new.fill(10,0)
100
+ a2 = Array.(Integer).new.fill(10,1)
101
+ c = Array.('Array[Integer]').new
102
+ c << a1
103
+ c << a2
104
+ c.flatten
105
+ __END
106
+ result = language.check(code)
107
+ expect(result.ruby_type).to eq(Array)
108
+ expect(result.type_vars.first.bound.ruby_type).to eq(Object)
109
+ end
110
+
111
+ it 'type checks / Integer -> Array[Object]' do
112
+ code = <<__END
113
+ a1 = Array.(Integer).new.fill(10,0)
114
+ a2 = Array.(Integer).new.fill(10,1)
115
+ c = Array.('Array[Integer]').new
116
+ c << a1
117
+ c << a2
118
+ c.flatten(2)
119
+ __END
120
+ result = language.check(code)
121
+ expect(result.ruby_type).to eq(Array)
122
+ expect(result.type_vars.first.bound.ruby_type).to eq(Object)
123
+ end
124
+ end
125
+
126
+ describe '#include?' do
127
+ it 'type checks / [T] -> Boolean' do
128
+ code = <<__END
129
+ a = Array.(Integer).new.fill(10,0)
130
+
131
+ a.include?(1)
132
+ __END
133
+ result = language.check(code)
134
+ expect(result.ruby_type).to eq(TrueClass)
135
+
136
+ code = <<__END
137
+ a = Array.(Integer).new.fill(10,0)
138
+
139
+ a.include?('a')
140
+ __END
141
+ expect {
142
+ language.check(code)
143
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
144
+ end
145
+ end
146
+
147
+ describe '#insert' do
148
+ it 'type checks / Integer -> [T] -> Array[T]' do
149
+ code = <<__END
150
+ a = Array.(Integer).new.fill(10,0)
151
+
152
+ a.insert(0, 1)
153
+
154
+ a.insert(0, 1, 2, 3)
155
+ __END
156
+
157
+ result = language.check(code)
158
+ expect(result.ruby_type).to eq(Array)
159
+ expect(result.type_vars.first.bound.ruby_type).to eq(Integer)
160
+ end
161
+ end
162
+
163
+ describe '#last' do
164
+ it 'type checks / -> [T]' do
165
+ code = <<__END
166
+ a = Array.(Integer).new.fill(10,0)
167
+ a.last
168
+ __END
169
+ result = language.check(code)
170
+ expect(result.ruby_type).to eq(Integer)
171
+ end
172
+
173
+ it 'type checks / Integer -> Array[T]' do
174
+ code = <<__END
175
+ a = Array.(Integer).new.fill(10,0)
176
+ a.last(5)
177
+ __END
178
+ result = language.check(code)
179
+ expect(result.ruby_type).to eq(Array)
180
+ expect(result.type_vars.first.bound.ruby_type).to eq(Integer)
181
+ end
182
+ end
183
+
184
+ describe '#map[E]' do
185
+ it 'type checks / &([T] -> [E]) -> Array[E]' do
186
+ result = language.check('Array.(Integer).new(10,0).map{ |e| e.to_s }')
187
+ expect(result.ruby_type).to eq(Array)
188
+ expect(result.type_vars.first.bound.ruby_type).to eq(String)
189
+ end
190
+ end
191
+
192
+ describe '#permutation' do
193
+ it 'type checks / -> Array[Array[T]]' do
194
+ result = language.check('Array.(Integer).new(10,0).permutation')
195
+ expect(result.ruby_type).to eq(Array)
196
+ expect(result.type_vars.first.bound.ruby_type).to eq(Array)
197
+ expect(result.type_vars.first.bound.type_vars.first.bound.ruby_type).to eq(Integer)
198
+ end
199
+ end
200
+
201
+ describe '#product' do
202
+ it 'type checks / Array[T]... -> Array[Array[T]]' do
203
+ result = language.check('Array.(Integer).new(10,0).product(Array.(Integer).new(5,1), Array.(Integer).new(5,2))')
204
+ expect(result.ruby_type).to eq(Array)
205
+ expect(result.type_vars.first.bound.ruby_type).to eq(Array)
206
+ expect(result.type_vars.first.bound.type_vars.first.bound.ruby_type).to eq(Integer)
207
+ end
208
+ end
209
+
210
+ describe '#push' do
211
+
212
+ it 'type checks / [T]... -> Array[T]' do
213
+ result = language.check('Array.(Integer).new.push(1,2,3)')
214
+ expect(result.ruby_type).to eq(Array)
215
+ expect(result.type_vars.first.bound.ruby_type).to eq(Integer)
216
+
217
+ expect {
218
+ language.check('Array.(Integer).new.push(1,2.0,3)')
219
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
220
+ end
221
+ end
222
+
223
+ describe '#sort' do
224
+ it 'type checks / &([T] -> [T] -> Integer) -> Array[T]' do
225
+ code = <<__END
226
+ a = Array.(Integer).new.fill(10,0)
227
+ a.sort
228
+ __END
229
+ result = language.check(code)
230
+ expect(result.ruby_type).to eq(Array)
231
+ expect(result.type_vars.first.bound.ruby_type).to eq(Integer)
232
+
233
+ code = <<__END
234
+ a = Array.(Integer).new.fill(10,0)
235
+ ts '#tcii / Integer -> Integer -> Integer'
236
+ def tcii(a,b); a <=> b; end
237
+ a.sort{ |a,b| tcii(a,b) }
238
+ __END
239
+ result = language.check(code)
240
+ expect(result.ruby_type).to eq(Array)
241
+ expect(result.type_vars.first.bound.ruby_type).to eq(Integer)
242
+
243
+ code = <<__END
244
+ ts '#tcss / String -> String -> Integer'
245
+ def tcss(a,b); -1; end
246
+ a = Array.(Integer).new.fill(10,0)
247
+ a.sort{ |a,b| tcss(a,b) }
248
+ __END
249
+
250
+ expect {
251
+ language.check(code)
252
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
253
+ end
254
+ end
255
+
256
+ describe '#to_s' do
257
+ it 'type checks / -> Hash[T][T]' do
258
+ result = language.check('Array.(Integer).new.to_h')
259
+ expect(result.ruby_type).to eq(Hash)
260
+ expect(result.type_vars.map(&:bound).map(&:ruby_type)).to eq([Integer, Integer])
261
+ end
262
+ end
263
+ end
@@ -0,0 +1,12 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe Class do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ describe '#initialize' do
7
+ it 'type checks / Class -> Class' do
8
+ result = language.check('Class.new(Object)')
9
+ expect(result.ruby_type).to eq(Class)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,278 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe Enumerable do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ describe '#all?' do
7
+ context 'for Array' do
8
+ it 'type checks / &([T] -> Boolean) -> Boolean' do
9
+ code = <<__CODE
10
+ ts '#int_fn / Integer -> Boolean'
11
+ def int_fn(e); true; end
12
+ Array.(Integer).new.all? { |e| int_fn(e) }
13
+ __CODE
14
+ result = language.check(code)
15
+
16
+ expect(result.to_s).to eq('Boolean')
17
+
18
+ expect {
19
+ code = <<__CODE
20
+ ts '#str_fn / String -> Boolean'
21
+ def str_fn(e); true; end
22
+ Array.(Integer).new.all? { |e| str_fn(e) }
23
+ __CODE
24
+ language.check(code)
25
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
26
+ end
27
+ end
28
+
29
+ context 'for Hash' do
30
+ it 'type checks / &([T] -> Boolean) -> Boolean' do
31
+ code = <<__CODE
32
+ ts '#str_int_fn / String -> Integer -> Boolean'
33
+ def str_int_fn(s,i); true; end
34
+ Hash.(String,Integer).new.all? { |k,v| str_int_fn(k,v) }
35
+ __CODE
36
+ result = language.check(code)
37
+
38
+ expect(result.to_s).to eq('Boolean')
39
+
40
+ code = <<__CODE
41
+ ts '#str_int_fn / String -> Integer -> Boolean'
42
+ def str_int_fn(s,i); true; end
43
+ Hash.(String,Integer).new.all? { |p| str_int_fn(p.first,p.second) }
44
+ __CODE
45
+ result = language.check(code)
46
+
47
+ expect(result.to_s).to eq('Boolean')
48
+
49
+ expect {
50
+ code = <<__CODE
51
+ ts '#str_str_fn / String -> String -> Boolean'
52
+ def str_str_fn(s,i); true; end
53
+ Hash.(String,Integer).new.all? { |k,v| str_str_fn(k,v) }
54
+ __CODE
55
+ language.check(code)
56
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
57
+
58
+ expect {
59
+ code = <<__CODE
60
+ ts '#str_str_fn / String -> String -> Boolean'
61
+ def str_str_fn(s,i); true; end
62
+ Hash.(String,Integer).new.all? { |p| str_str_fn(p.first,p.second) }
63
+ __CODE
64
+ language.check(code)
65
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
66
+ end
67
+ end
68
+ end
69
+
70
+ describe '#chunk' do
71
+ describe '&([T] -> Boolean) -> Enumerator[Pair[Boolean][Array[T]]]' do
72
+ it 'type checks it correctly, positive case' do
73
+ code = <<__CODE
74
+ ts "#int_bool_fn / Integer -> Boolean"
75
+ def int_bool_fn(i); true; end
76
+
77
+ ts '#bool_int_ary_fn / Boolean -> Array[Integer] -> unit'
78
+ def bool_int_ary_fn(b,a); nil; end
79
+
80
+ [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5].chunk { |n|
81
+ int_bool_fn(n)
82
+ }.each { |even, ary|
83
+ bool_int_ary_fn(even, ary)
84
+ }
85
+ __CODE
86
+ result = language.check(code)
87
+
88
+ expect(result.to_s).to eq('Object')
89
+ end
90
+
91
+ it 'type checks it correctly, negative case 1' do
92
+ code = <<__CODE
93
+ ts "#float_bool_fn / Float -> Boolean"
94
+ def float_bool_fn(f); true; end
95
+
96
+ [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5].chunk { |n|
97
+ float_bool_fn(n)
98
+ }
99
+ __CODE
100
+
101
+ expect {
102
+ language.check(code)
103
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
104
+ end
105
+
106
+ it 'type checks it correctly, negative case 2' do
107
+ code = <<__CODE
108
+ ts "#int_bool_fn / Integer -> Boolean"
109
+ def int_bool_fn(i); true; end
110
+
111
+ ts "#int_fn / Integer -> unit"
112
+ def int_fn(i); nil; end
113
+
114
+ [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5].chunk { |n|
115
+ int_bool_fn(n)
116
+ }.each { |b,i|
117
+ int_fn(i)
118
+ }
119
+ __CODE
120
+
121
+ expect {
122
+ language.check(code)
123
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
124
+ end
125
+ end
126
+ end
127
+
128
+ describe '#detect' do
129
+ describe '&([T] -> Boolean) -> [T]' do
130
+ it 'type checks it correctly, positive case' do
131
+ code = <<__CODE
132
+ ts "#int_bool_fn / Integer -> Boolean"
133
+ def int_bool_fn(i); true; end
134
+
135
+ [1, 2, 3, 4].detect{ |i| int_bool_fn(i) }
136
+ __CODE
137
+ result = language.check(code)
138
+
139
+ expect(result.to_s).to eq('Integer')
140
+ end
141
+
142
+ it 'type checks it correctly, negative case' do
143
+ code = <<__CODE
144
+ ts "#float_bool_fn / Float -> Boolean"
145
+ def float_bool_fn(f); true; end
146
+
147
+ [1, 2, 3, 4].detect { |i| float_bool_fn(i) }
148
+ __CODE
149
+ expect {
150
+ language.check(code)
151
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
152
+ end
153
+ end
154
+
155
+ describe '[T] -> Enumerator[T]' do
156
+ it 'type checks it correctly, positive case' do
157
+ code = <<__CODE
158
+ [1, 2, 3, 4].detect
159
+ __CODE
160
+ result = language.check(code)
161
+
162
+ expect(result.to_s).to eq('Enumerator[Integer]')
163
+ end
164
+ end
165
+ end
166
+
167
+ describe '#each_cons' do
168
+ describe 'Integer -> Enumerator[Array[T]]' do
169
+ it 'type checks it correctly, positive case' do
170
+ code = <<__CODE
171
+ [1,2,3].each_cons(2)
172
+ __CODE
173
+ result = language.check(code)
174
+
175
+ expect(result.to_s).to eq('Enumerator[Array[Integer]]')
176
+ end
177
+
178
+ it 'type checks it correctly, positive case' do
179
+ code = <<__CODE
180
+ [1,2,3].each_cons(2).first
181
+ __CODE
182
+ result = language.check(code)
183
+
184
+ expect(result.to_s).to eq('Array[Integer]')
185
+ end
186
+ end
187
+ end
188
+
189
+ describe '#grep' do
190
+ describe 'Regexp -> Array[T]' do
191
+ it 'type checks it correctly' do
192
+ result = language.check('["1","2","3","e","f","4"].grep(/\d/)')
193
+ expect(result.to_s).to eq('Array[String]')
194
+ end
195
+ end
196
+
197
+ describe '[E] / Regexp -> &([T] -> [E]) -> Array[E]' do
198
+ it 'type checks it correctly, positive case' do
199
+ code = <<__CODE
200
+ ts '#s_to_i / String -> Integer'
201
+ def s_to_i(s); 0; end
202
+
203
+ ["1","2","3","e","f","4"].grep(/\d/){ |e| s_to_i(e) }
204
+ __CODE
205
+ result = language.check(code)
206
+ expect(result.to_s).to eq('Array[Integer]')
207
+ end
208
+
209
+ it 'type checks it correctly, negative case' do
210
+ code = <<__CODE
211
+ ts '#f_to_i / Float -> Integer'
212
+ def f_to_i(s); 0; end
213
+
214
+ ["1","2","3","e","f","4"].grep(/\d/){ |e| f_to_i(e) }
215
+ __CODE
216
+ expect {
217
+ language.check(code)
218
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
219
+ end
220
+ end
221
+ end
222
+
223
+ describe '#max' do
224
+ describe '&(Pair[T][T] -> Integer) -> [T]' do
225
+ it 'type checks it correctly, positive case' do
226
+ code = <<__CODE
227
+ ts '#int_int_fn / Integer -> Integer -> Integer'
228
+ def int_int_fn(a,b); a+b; end
229
+
230
+ [1,2,3,4,5].max { |a,b| int_int_fn(a,b) }
231
+ __CODE
232
+ result = language.check(code)
233
+ expect(result.to_s).to eq('Integer')
234
+ end
235
+ end
236
+ end
237
+
238
+ describe '#partition' do
239
+ describe '&([T] -> Boolean) -> Pair[Array[T]][Array[T]]' do
240
+ it 'type checks it correclty, positive case' do
241
+ code = <<__CODE
242
+ ts '#odd? / Integer -> Boolean'
243
+ def odd?(e); false; end
244
+
245
+ [1,2,3,4,5,6].partition { |e| odd?(e) }
246
+ __CODE
247
+ result = language.check(code)
248
+ expect(result.to_s).to eq('Pair[Array[Integer]][Array[Integer]]')
249
+ end
250
+ end
251
+ end
252
+
253
+ describe '#sort_by' do
254
+ describe '[Comparable[E]] / &([T] -> [E]) -> Array[T]' do
255
+ it 'type checks it correctly, positive case' do
256
+ code = <<__CODE
257
+ ["apple", "pear", "fig" ].sort_by {|word| word.length }
258
+ __CODE
259
+
260
+ result = language.check(code)
261
+ expect(result.to_s).to eq('Array[String]')
262
+ end
263
+
264
+ it 'type checks it correctly, negative case' do
265
+ code = <<__CODE
266
+ ts '#uncomparable / String -> Object'
267
+ def uncomparable(s); Object.new; end
268
+
269
+ ->(){ ["apple", "pear", "fig" ].sort_by {|word| uncomparable(word) } }
270
+ __CODE
271
+
272
+ expect {
273
+ language.check(code)
274
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
275
+ end
276
+ end
277
+ end
278
+ end
@@ -0,0 +1,101 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe Enumerator do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ describe '#initialize' do
7
+ it 'type checks / Integer -> Enumerator[T]' do
8
+ result = language.check('Enumerator.(Integer).new(10)')
9
+ expect(result.to_s).to eq('Enumerator[Integer]')
10
+ end
11
+
12
+ it 'type checks / &(Enumerator::Yielder[T] -> unit) -> Enumerator[T]' do
13
+ result = language.check('Enumerator.(Integer).new { |y| y.yield(10) }')
14
+ expect(result.to_s).to eq('Enumerator[Integer]')
15
+
16
+ expect {
17
+ language.check('Enumerator.(Integer).new { |y| y.yield("string") }')
18
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
19
+ end
20
+
21
+ it 'type checks / Object -> Symbol -> Enumerator[T]' do
22
+ result = language.check('Enumerator.(String).new Object.new')
23
+ expect(result.to_s).to eq('Enumerator[String]')
24
+ end
25
+ end
26
+
27
+ describe '#each' do
28
+ it 'type checks / -> Enumerator[T]' do
29
+ result = language.check('Enumerator.(Integer).new { |y| y.yield(10) }.each')
30
+ expect(result.to_s).to eq('Enumerator[Integer]')
31
+ end
32
+
33
+ it 'type checks / &([T] -> unit) -> Object' do
34
+ code = <<__CODE
35
+ Enumerator.(Integer).new { |y| y.yield(10) }.each do |i|
36
+ i + 1
37
+ end
38
+ __CODE
39
+ result = language.check(code)
40
+ expect(result.to_s).to eq('Object')
41
+
42
+ code = <<__CODE
43
+ ts '#str_fn / String -> unit'
44
+ def str_fn(s); end
45
+
46
+ Enumerator.(Integer).new { |y| y.yield(10) }.each do |i|
47
+ str_fn(i)
48
+ end
49
+ __CODE
50
+ expect {
51
+ language.check(code)
52
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
53
+ end
54
+ end
55
+
56
+ describe '#each_with_index' do
57
+ it 'type checks / -> Enumerator[Pair[T][Integer]]' do
58
+ result = language.check('Enumerator.(Integer).new { |y| y.yield(10) }.each_with_index')
59
+
60
+ expect(result.to_s).to eq('Enumerator[Pair[Integer][Integer]]')
61
+ end
62
+
63
+ it 'type checks / -> Enumerator[Pair[T][Integer]] multiple invocations' do
64
+ result = language.check('Enumerator.(Integer).new { |y| y.yield(10) }.each_with_index.each_with_index')
65
+ expect(result.to_s).to eq('Enumerator[Pair[Pair[Integer][Integer]][Integer]]')
66
+ end
67
+
68
+ it 'type checks / &([T] -> Integer -> unit) -> Object' do
69
+ code = <<__CODE
70
+ ts '#int_int_fn / Integer -> Integer -> Integer'
71
+ def int_int_fn(x,y); x + y; end
72
+ Enumerator.(Integer).new { |y| y.yield(10) }.each_with_index do |e, i|
73
+ int_int_fn(e,i)
74
+ end
75
+ __CODE
76
+
77
+ result = language.check(code)
78
+ expect(result.to_s).to eq('Object')
79
+
80
+ expect {
81
+ code = <<__CODE
82
+ ts '#int_int_fn / Integer -> Integer -> Integer'
83
+ def int_int_fn(x,y); y; end
84
+ Enumerator.(String).new { |y| y.yield("str") }.each_with_index do |e, i|
85
+ int_int_fn(e,i)
86
+ end
87
+ __CODE
88
+
89
+ result = language.check(code)
90
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
91
+ end
92
+ end
93
+
94
+ describe '#each_with_object' do
95
+ it 'type checks[E] / -> Enumerator[Pair[T][E]]' do
96
+ result = language.check('Enumerator.(Integer).new { |y| y.yield(10) }.each_with_object("String")')
97
+
98
+ expect(result.to_s).to eq('Enumerator[Pair[Integer][String]]')
99
+ end
100
+ end
101
+ end