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,503 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe BasicObject do
4
+
5
+ before :each do
6
+ ::BasicObject::TypeRegistry.clear
7
+ end
8
+
9
+ it 'parses type signatures and store data into the type registry' do
10
+ $TYPECHECK = true
11
+ code = <<__END
12
+ class A
13
+
14
+ ts 'A#test / String -> unit'
15
+ def test(msg)
16
+ puts msg
17
+ end
18
+
19
+ ts 'A.class_method / Int -> Int'
20
+
21
+ ts '#abbrev / String -> String'
22
+ ts '.abbrev / String -> String'
23
+ end
24
+
25
+ ts 'B#other_test / Int -> unit'
26
+ ts 'A#other_test / Int -> unit'
27
+ __END
28
+
29
+ eval(code)
30
+
31
+ expect(::BasicObject::TypeRegistry.send(:parser_registry)['instance|A']['test']).to eq([['String', :unit]])
32
+ expect(::BasicObject::TypeRegistry.send(:parser_registry)['class|A']['class_method']).to eq([['Int', 'Int']])
33
+ expect(::BasicObject::TypeRegistry.send(:parser_registry)['instance|B']['other_test']).to eq([['Int', :unit]])
34
+ expect(::BasicObject::TypeRegistry.send(:parser_registry)['instance|A']['other_test']).to eq([['Int', :unit]])
35
+ expect(::BasicObject::TypeRegistry.send(:parser_registry)['instance|A']['abbrev']).to eq([['String', 'String']])
36
+ expect(::BasicObject::TypeRegistry.send(:parser_registry)['class|A']['abbrev']).to eq([['String', 'String']])
37
+ end
38
+
39
+ it 'normalizes the parsed types with information about the defined classes' do
40
+ $TYPECHECK = true
41
+ code = <<__END
42
+ class A
43
+ ts '#inc / Integer -> Integer'
44
+ def inc(i)
45
+ i+= 1
46
+ i
47
+ end
48
+ end
49
+
50
+ class B
51
+ ts '#consume_a / A -> Integer'
52
+ def consume_a(a)
53
+ 0
54
+ end
55
+
56
+ ts '#consume_b / -> Boolean'
57
+ def consume_b
58
+ 1
59
+ end
60
+ end
61
+ __END
62
+
63
+ eval(code)
64
+
65
+ ::BasicObject::TypeRegistry.normalize_types!
66
+
67
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,A]]["inc"].size).to eq(1)
68
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,A]]["inc"].first.to_s).to eq("(Integer -> Integer)")
69
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,B]]["consume_a"].size).to eq(1)
70
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,B]]["consume_a"].first.to_s).to eq("(A -> Integer)")
71
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,B]]["consume_b"].size).to eq(1)
72
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,B]]["consume_b"].first.to_s).to eq("( -> Boolean)")
73
+ end
74
+
75
+ it 'normalizes types with generic methods' do
76
+ code = <<__END
77
+ class A
78
+ ts '#m[E][Y]/ [E] -> Integer -> [Y]'
79
+ def m(x,i); end
80
+ end
81
+ __END
82
+
83
+ eval(code)
84
+
85
+ ::BasicObject::TypeRegistry.normalize_types!
86
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,A]]["m"].size).to eq(1)
87
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,A]]["m"].first.to_s).to eq("(A:m:E::[?,?], Integer -> A:m:Y::[?,?])")
88
+ end
89
+ it 'parses field type signatures and store the result in the registry' do
90
+ $TYPECHECK = true
91
+ code = <<__END
92
+ class A
93
+ ts 'A\#@a / Integer'
94
+ attr_accessor :a
95
+
96
+ ts '#inc / Integer -> Integer'
97
+ def inc(i)
98
+ @a = i+ 1
99
+ @a
100
+ end
101
+ end
102
+ __END
103
+
104
+ eval(code)
105
+
106
+
107
+ expect(::BasicObject::TypeRegistry.send(:parser_registry)['instance_variable|A']['@a']).to eq(['Integer'])
108
+ end
109
+
110
+ it 'normalizes types signatures for fields and store the result in the registry' do
111
+ $TYPECHECK = true
112
+ code = <<__END
113
+ class A
114
+ ts 'A\#@a / Integer'
115
+ attr_accessor :a
116
+
117
+ ts '#inc / Integer -> Integer'
118
+ def inc(i)
119
+ @a = i+ 1
120
+ @a
121
+ end
122
+ end
123
+ __END
124
+
125
+ eval(code)
126
+
127
+ ::BasicObject::TypeRegistry.normalize_types!
128
+
129
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance_variable,A]]["@a"].to_s).to eq('Integer')
130
+ end
131
+
132
+ it 'parses type function with multiple arguments' do
133
+ $TYPECHECK = true
134
+ code = <<__END
135
+ class A
136
+ ts '#func / Integer -> Integer -> Integer -> Integer'
137
+ def func(i,j,k)
138
+ i + j + k
139
+ end
140
+ end
141
+ __END
142
+
143
+ eval(code)
144
+
145
+ ::BasicObject::TypeRegistry.normalize_types!
146
+
147
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,A]]["func"].size).to eq(1)
148
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,A]]["func"].first.to_s).to eq('(Integer, Integer, Integer -> Integer)')
149
+ end
150
+
151
+
152
+ it 'parses type function with multiple arguments' do
153
+ $TYPECHECK = true
154
+ code = <<__END
155
+ class A
156
+ ts '#func / Integer -> &(Integer -> Integer -> Integer) -> Integer'
157
+ def func(i)
158
+ yield i, i
159
+ end
160
+ end
161
+ __END
162
+
163
+ eval(code)
164
+
165
+ ::BasicObject::TypeRegistry.normalize_types!
166
+
167
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,A]]["func"].size).to eq(1)
168
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,A]]["func"].first.to_s).to eq('(Integer, &(Integer, Integer -> Integer) -> Integer)')
169
+ end
170
+
171
+ it 'parses type functions with no arguments' do
172
+ $TYPECHECK = true
173
+ code = <<__END
174
+ class A
175
+ ts '#func / Integer -> Integer'
176
+ def func(i)
177
+ 1
178
+ end
179
+ end
180
+ __END
181
+
182
+ eval(code)
183
+
184
+ ::BasicObject::TypeRegistry.normalize_types!
185
+
186
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,A]]["func"].size).to eq(1)
187
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,A]]["func"].first.to_s).to eq('(Integer -> Integer)')
188
+ end
189
+
190
+ it 'parses type functions with functions with no arguments as argument' do
191
+ $TYPECHECK = true
192
+ code = <<__END
193
+ class A
194
+ ts '#func / Integer -> ( -> Integer) -> Integer'
195
+ def func(i, f)
196
+ f[]
197
+ end
198
+ end
199
+ __END
200
+
201
+ eval(code)
202
+
203
+ ::BasicObject::TypeRegistry.normalize_types!
204
+
205
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,A]]["func"].size).to eq(1)
206
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,A]]["func"].first.to_s).to eq('(Integer, ( -> Integer) -> Integer)')
207
+ end
208
+
209
+ it 'parses generic types' do
210
+ $TYPECHECK = true
211
+ code = <<__END
212
+ ts 'type Array[X]'
213
+
214
+ ts 'type Container[X<Numeric]'
215
+ class Container
216
+
217
+ ts '#push / [X<Numeric] -> unit'
218
+ def push(value)
219
+ @value = value
220
+ end
221
+
222
+ ts '#pop / -> [X<Numeric]'
223
+ def pop
224
+ @value
225
+ end
226
+
227
+ ts '#test0 / -> [X>Numeric]'
228
+ def test0
229
+ @value
230
+ end
231
+
232
+ ts '#test1 / Array[X] -> unit'
233
+ def test1(xs)
234
+ @value = xs.first
235
+ end
236
+ end
237
+ __END
238
+
239
+ eval(code)
240
+ ::BasicObject::TypeRegistry.normalize_types!
241
+ expect(::BasicObject::TypeRegistry.send(:generic_types_registry)[Container]).to be_instance_of(TypedRb::Types::TyGenericSingletonObject)
242
+ expect(::BasicObject::TypeRegistry.send(:generic_types_registry)[Container].ruby_type).to eq(Container)
243
+ expect(::BasicObject::TypeRegistry.send(:generic_types_registry)[Container].type_vars[0].variable).to eq('Container:X')
244
+ expect(::BasicObject::TypeRegistry.send(:generic_types_registry)[Container].type_vars[0].upper_bound.ruby_type).to eq(Numeric)
245
+
246
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,Container]]['push'].size).to eq(1)
247
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,Container]]['push'].first).to be_instance_of(TypedRb::Types::TyGenericFunction)
248
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,Container]]['push'].first.from[0].variable).to eq('Container:X')
249
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,Container]]['push'].first.from[0].upper_bound.ruby_type).to eq(Numeric)
250
+
251
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,Container]]['pop'].size).to eq(1)
252
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,Container]]['pop'].first.to.variable).to eq('Container:X')
253
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,Container]]['pop'].first.to.upper_bound.ruby_type).to eq(Numeric)
254
+
255
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,Container]]['test1'].size).to eq(1)
256
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,Container]]['test1'].first).to be_instance_of(TypedRb::Types::TyGenericFunction)
257
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,Container]]['test0'].size).to eq(1)
258
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,Container]]['test0'].first).to be_instance_of(TypedRb::Types::TyGenericFunction)
259
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,Container]]['test0'].first.to).to be_instance_of(TypedRb::Types::Polymorphism::TypeVariable)
260
+ expect(::BasicObject::TypeRegistry.send(:registry)[[:instance,Container]]['test0'].first.to.lower_bound.ruby_type).to eq(Numeric)
261
+ end
262
+
263
+ it 'parses concrete generic types' do
264
+ $TYPECHECK = true
265
+ code = <<__END
266
+ ts 'type Array[X]'
267
+ class Array; end
268
+
269
+ ts 'type Cnt1[X<Numeric]'
270
+ class Cnt1
271
+
272
+ ts '#f1 / Array[Integer] -> unit'
273
+ def f1(a); end
274
+
275
+ ts '#f2 / Array[X] -> unit'
276
+ def f2(a); end
277
+
278
+ ts '#f3 / Array[? < Numeric] -> unit'
279
+ def f3(a); end
280
+ end
281
+ __END
282
+
283
+ eval(code)
284
+ ::BasicObject::TypeRegistry.normalize_types!
285
+
286
+ f1_type = ::BasicObject::TypeRegistry.send(:registry)[[:instance,Cnt1]]['f1'].first
287
+ f2_type = ::BasicObject::TypeRegistry.send(:registry)[[:instance,Cnt1]]['f2'].first
288
+ f3_type = ::BasicObject::TypeRegistry.send(:registry)[[:instance,Cnt1]]['f3'].first
289
+ expect(f1_type).to be_instance_of(TypedRb::Types::TyFunction)
290
+ expect(f1_type.from.first).to be_instance_of(TypedRb::Types::TyGenericObject)
291
+ expect(f1_type.from.first.type_vars.first.bound.ruby_type).to eq(Integer)
292
+ expect(f1_type.from.first.type_vars.first.upper_bound.ruby_type).to eq(Integer)
293
+ expect(f1_type.from.first.type_vars.first.lower_bound.ruby_type).to eq(Integer)
294
+ expect(f1_type.from.first.type_vars.first.variable).to eq('Array:X')
295
+ expect(f2_type.from.first).to be_instance_of(TypedRb::Types::TyGenericSingletonObject)
296
+ expect(f2_type.from.first.type_vars.first.bound).to eq(nil)
297
+ expect(f2_type.from.first.type_vars.first.variable).to eq('Cnt1:X')
298
+
299
+ expect(f3_type.from.first).to be_instance_of(TypedRb::Types::TyGenericSingletonObject)
300
+ expect(f3_type.from.first.type_vars.first.bound).to eq(nil)
301
+ expect(f3_type.from.first.type_vars.first.upper_bound.ruby_type).to eq(Numeric)
302
+ expect(f3_type.from.first.type_vars.first.lower_bound).to eq(nil)
303
+ expect(f3_type.from.first.type_vars.first.variable).to match(/Cnt1:Array:X:[\d]+/)
304
+ end
305
+
306
+ it 'parses function types with variable rest args' do
307
+ $TYPECHECK = true
308
+ code = <<__END
309
+ ts 'type Array[X]'
310
+ class Array; end
311
+
312
+ class Cnt2
313
+
314
+ ts '#f1 / String -> Integer... -> unit'
315
+ def f1(s, *i); end
316
+
317
+ end
318
+ __END
319
+
320
+ eval(code)
321
+ ::BasicObject::TypeRegistry.normalize_types!
322
+
323
+ f1_type = ::BasicObject::TypeRegistry.send(:registry)[[:instance,Cnt2]]['f1'].first
324
+ expect(f1_type.from[1]).to be_instance_of(TypedRb::Types::TyGenericObject)
325
+ expect(f1_type.from[1].type_vars.first.bound.ruby_type).to eq(Integer)
326
+ expect(f1_type.from[1].type_vars.first.variable).to eq('Array:T')
327
+ end
328
+
329
+ it 'parses function types with block arguments' do
330
+ $TYPECHECK = true
331
+ code = <<__END
332
+ class Cnt3
333
+ ts '#wblock / Integer -> &(Integer -> Integer) -> Integer'
334
+ def wblock(x)
335
+ yield x
336
+ end
337
+ end
338
+ __END
339
+
340
+ eval(code)
341
+ ::BasicObject::TypeRegistry.normalize_types!
342
+
343
+ wblock_type = ::BasicObject::TypeRegistry.send(:registry)[[:instance,Cnt3]]['wblock'].first
344
+ expect(wblock_type.block_type.from.size).to eq(1)
345
+ expect(wblock_type.block_type.from.first.ruby_type).to eq(Integer)
346
+ expect(wblock_type.block_type.to.ruby_type).to eq(Integer)
347
+ end
348
+
349
+ let(:language) { TypedRb::Language.new }
350
+
351
+ it 'handles function signatures with and without blocks' do
352
+ $TYPECHECK = false
353
+
354
+ code = <<__CODE
355
+ class MBT1
356
+ def test(x); end
357
+ end
358
+ __CODE
359
+
360
+ eval(code)
361
+
362
+ $TYPECHECK = true
363
+
364
+ code = <<__CODE
365
+ class MBT1
366
+ ts '#test / Integer -> Integer'
367
+ ts '#test / Integer -> &(String -> String) -> String'
368
+ end
369
+
370
+ ts '#t_int_str / Integer -> String -> String'
371
+ def t_int_str(a,b); b; end
372
+
373
+ mbt1 = MBT1.new
374
+
375
+ a = mbt1.test(1)
376
+ b = mbt1.test(1) { |x| 'string' }
377
+
378
+ t_int_str(a,b)
379
+ __CODE
380
+
381
+ result = language.check(code)
382
+ expect(result.ruby_type).to eq(String)
383
+ end
384
+
385
+ context 'handles bounds in method parameters' do
386
+ it 'handles positive case' do
387
+ code = <<__CODE
388
+
389
+ class TMBSA
390
+ ts '#tmbs1[E < Numeric] / [E] -> [E]'
391
+ def tmbs1(x); x; end
392
+ end
393
+
394
+ TMBSA.new.tmbs1(1)
395
+ __CODE
396
+
397
+ result = language.check(code)
398
+ expect(result.ruby_type).to eq(Integer)
399
+ end
400
+
401
+ it 'handles negative case' do
402
+ code = <<__CODE
403
+
404
+ class TMBSA
405
+ ts '#tmbs2[E < Numeric] / [E] -> [E]'
406
+ def tmbs2(x); x; end
407
+ end
408
+
409
+ TMBSA.new.tmbs2('string')
410
+ __CODE
411
+
412
+ expect {
413
+ language.check(code)
414
+ }.to raise_error(TypedRb::TypeCheckError)
415
+ end
416
+ end
417
+
418
+ it 'handles method type variables in main object' do
419
+ code = <<__END
420
+
421
+ ts '#tmm[E] / [E] -> [E]'
422
+ def tmm(x); x; end
423
+
424
+ tmm(2)
425
+ tmm('string')
426
+ __END
427
+
428
+ result = language.check(code)
429
+
430
+ expect(result.ruby_type).to eq(String)
431
+ end
432
+
433
+ it 'handles combinations of optional parameters' do
434
+ $TYPECHECK = false
435
+ eval('class TMBSB; def tcmm1(x, y=2, *z); x; end; end')
436
+ $TYPECHECK = true
437
+ code = <<__END
438
+ class TMBSB
439
+ ts '#tcmm1 / Integer -> Integer'
440
+ ts '#tcmm1 / Integer -> Integer -> Integer'
441
+ ts '#tcmm1 / Integer -> Integer -> String... -> Integer'
442
+ end
443
+ __END
444
+
445
+ case1 = "#{code}; TMBSB.new.tcmm1(1)"
446
+ result = language.check(case1)
447
+ expect(result.ruby_type).to eq(Integer)
448
+
449
+ case2 = "#{code}; TMBSB.new.tcmm1(1,1)"
450
+ result = language.check(case2)
451
+ expect(result.ruby_type).to eq(Integer)
452
+
453
+ case3 = "#{code}; TMBSB.new.tcmm1(1,1,'a')"
454
+ result = language.check(case3)
455
+ expect(result.ruby_type).to eq(Integer)
456
+
457
+ case4 = "#{code}; TMBSB.new.tcmm1(1,1,'a','a')"
458
+ result = language.check(case4)
459
+ expect(result.ruby_type).to eq(Integer)
460
+
461
+ expect {
462
+ case5 = "#{code}; TMBSB.new.tcmm1(1,1,'a','a',2)"
463
+ language.check(case5)
464
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
465
+ end
466
+
467
+ describe '.find' do
468
+
469
+ it 'finds registered function types' do
470
+ $TYPECHECK = true
471
+ code = <<__END
472
+ ts 'type Container[X<Numeric]'
473
+ class Container
474
+
475
+ ts '#push / [X<Numeric] -> unit'
476
+ def push(value)
477
+ @value = value
478
+ end
479
+
480
+ ts '#pop / -> [X<Numeric]'
481
+ def pop
482
+ @value
483
+ end
484
+
485
+ end
486
+ __END
487
+
488
+ eval(code)
489
+ ::BasicObject::TypeRegistry.normalize_types!
490
+
491
+
492
+ function_type = ::BasicObject::TypeRegistry.find(:instance, Container, :push).first
493
+ expect(function_type).to be_is_a(TypedRb::Types::TyFunction)
494
+ expect(function_type.from.size).to eq(1)
495
+ type_var = function_type.from.first
496
+ expect(type_var).to be_is_a(TypedRb::Types::Polymorphism::TypeVariable)
497
+ expect(type_var.variable).to eq('Container:X')
498
+ expect(type_var.upper_bound.ruby_type).to eq(Numeric)
499
+ expect(::BasicObject::TypeRegistry.send(:generic_types_registry)[Container].type_vars[0].variable).to eq(type_var.variable)
500
+ #expect(::BasicObject::TypeRegistry.generic_types_registry[Container].type_vars[0]).to eq(type_var)
501
+ end
502
+ end
503
+ end