typed.rb 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
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,103 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Types::TyDynamic do
4
+
5
+ context 'with not typed code' do
6
+
7
+ it 'supports untyped constructors' do
8
+ code = <<__CODE
9
+ class Dyn1
10
+
11
+ ts '#put / Integer -> unit'
12
+ def put(n)
13
+ @value = n
14
+ end
15
+
16
+ def take
17
+ @value
18
+ end
19
+
20
+ end
21
+
22
+ Dyn1.new
23
+ __CODE
24
+
25
+ parsed = TypedRb::Language.new.check(code)
26
+
27
+ expect(parsed.ruby_type).to eq(Dyn1)
28
+ end
29
+
30
+ it 'uses type Dynamic for the untyped code' do
31
+ code = <<__CODE
32
+ class Dyn1
33
+
34
+ ts '#put / Integer -> unit'
35
+ def put(n)
36
+ @value = n
37
+ end
38
+
39
+ def take
40
+ @value
41
+ end
42
+
43
+ end
44
+
45
+ Dyn1.new.take
46
+ __CODE
47
+
48
+ parsed = TypedRb::Language.new.check(code)
49
+
50
+ expect(parsed).to be_instance_of(described_class)
51
+ end
52
+
53
+ it 'can check mixed typed/untyped class definitions' do
54
+ code = <<__CODE
55
+ class Dyn1
56
+
57
+ def initialize(x); end
58
+
59
+ ts '#put / Integer -> Integer'
60
+ def put(n)
61
+ @value = n
62
+ end
63
+
64
+ def take
65
+ @value
66
+ end
67
+
68
+ end
69
+
70
+ Dyn1.new('test').put(3)
71
+ __CODE
72
+
73
+ parsed = TypedRb::Language.new.check(code)
74
+
75
+ expect(parsed.ruby_type).to eq(Integer)
76
+ end
77
+
78
+ it 'can check typed code invoking untyped code in the definition' do
79
+ code = <<__CODE
80
+ class Dyn1
81
+
82
+ def initialize(x); end
83
+
84
+ ts '#put / Integer -> Integer'
85
+ def put(n)
86
+ take + n
87
+ end
88
+
89
+ def take
90
+ 0
91
+ end
92
+
93
+ end
94
+
95
+ Dyn1.new('test').put(3)
96
+ __CODE
97
+
98
+ parsed = TypedRb::Language.new.check(code)
99
+
100
+ expect(parsed.ruby_type).to eq(Integer)
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,288 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Types::TyEither do
4
+ describe 'normal' do
5
+ it 'holds a type for the normal execution flow' do
6
+ either = described_class.new
7
+ ty_string = TypedRb::Types::TyString.new
8
+ either[:normal] = ty_string
9
+
10
+ expect(either.return?).to eq(false)
11
+ expect(either.break?).to eq(false)
12
+ expect(either.next?).to eq(false)
13
+ expect(either[:normal]).to eq(ty_string)
14
+ expect(either.has_jump?).to eq(false)
15
+ end
16
+ end
17
+
18
+ describe 'return' do
19
+ it 'holds a type for the return stack jump flow' do
20
+ either = described_class.new
21
+ ty_string = TypedRb::Types::TyString.new
22
+ ty_return = TypedRb::Types::TyStackJump.return(ty_string)
23
+ either[:return] = ty_return
24
+ expect(either.return?).to eq(true)
25
+ expect(either.break?).to eq(false)
26
+ expect(either.next?).to eq(false)
27
+ expect(either[:return]).to eq(ty_return)
28
+ expect(either.has_jump?).to eq(true)
29
+ end
30
+ end
31
+
32
+ describe 'break' do
33
+ it 'holds a type for the break stack jump flow' do
34
+ either = described_class.new
35
+ ty_string = TypedRb::Types::TyString.new
36
+ ty_break = TypedRb::Types::TyStackJump.break(ty_string)
37
+ either[:break] = ty_break
38
+ expect(either.return?).to eq(false)
39
+ expect(either.break?).to eq(true)
40
+ expect(either.next?).to eq(false)
41
+ expect(either[:break]).to eq(ty_break)
42
+ expect(either.has_jump?).to eq(true)
43
+ end
44
+ end
45
+
46
+ describe 'next' do
47
+ it 'holds a type for the next stack jump flow' do
48
+ either = described_class.new
49
+ ty_string = TypedRb::Types::TyString.new
50
+ ty_next = TypedRb::Types::TyStackJump.next(ty_string)
51
+ either[:next] = ty_next
52
+ expect(either.return?).to eq(false)
53
+ expect(either.break?).to eq(false)
54
+ expect(either.next?).to eq(true)
55
+ expect(either[:next]).to eq(ty_next)
56
+ expect(either.has_jump?).to eq(true)
57
+ end
58
+ end
59
+
60
+ describe '#[]' do
61
+ it 'raises an exception for an invalid type' do
62
+ either = described_class.new
63
+
64
+ expect {
65
+ either[:foo]# = TypedRb::Types::TyString.new
66
+ }.to raise_exception(Exception)
67
+ end
68
+ end
69
+
70
+ describe '#[]=' do
71
+ it 'raises an exception for an invalid type' do
72
+ either = described_class.new
73
+
74
+ expect {
75
+ either[:foo] = TypedRb::Types::TyString.new
76
+ }.to raise_exception(Exception)
77
+ end
78
+ end
79
+
80
+ describe '#compatible?' do
81
+ it 'delegates compatiblity check to the normal flow type' do
82
+ either = described_class.new
83
+ either[:normal] = TypedRb::Types::TyString.new
84
+
85
+ string_type = TypedRb::Types::TyString.new
86
+
87
+ expect(either.compatible?(string_type, :lt)).to eq(true)
88
+ expect {
89
+ float_type = TypedRb::Types::TyObject.new(Float)
90
+ either.compatible?(float_type, :lt)
91
+ }.to raise_exception(TypedRb::Types::UncomparableTypes)
92
+ end
93
+ end
94
+
95
+ describe '#compatible_either?' do
96
+ context 'with missing either values' do
97
+ it 'add the missing either values to the current type' do
98
+ either_a = described_class.new
99
+ either_b = described_class.new
100
+ ty_string = TypedRb::Types::TyString.new
101
+ either_a[:return] = TypedRb::Types::TyStackJump.return(ty_string)
102
+ either_b[:break] = TypedRb::Types::TyStackJump.break(ty_string)
103
+
104
+ either_a.compatible_either?(either_b)
105
+ expect(either_a[:return].return?).to eq(true)
106
+ expect(either_a[:break].break?).to eq(true)
107
+ end
108
+ end
109
+
110
+ context 'with matching either values' do
111
+
112
+ it 'computes the max type of normal types' do
113
+ either_a = described_class.new
114
+ either_b = described_class.new
115
+ ty_string = TypedRb::Types::TyString.new
116
+ either_a[:return] = TypedRb::Types::TyStackJump.return(ty_string)
117
+ either_b[:return] = TypedRb::Types::TyStackJump.return(ty_string)
118
+
119
+ expect {
120
+ either_a.compatible_either?(either_b)
121
+ }.to_not raise_exception
122
+
123
+ ty_float = TypedRb::Types::TyObject.new(Float)
124
+ either_b[:return] = TypedRb::Types::TyStackJump.return(ty_float)
125
+ either_a.compatible_either?(either_b)
126
+
127
+ expect(either_a[:return].wrapped_type.ruby_type).to eq(Object)
128
+ end
129
+
130
+ it 'adds constraints to type variables matching regular types'do
131
+ either_a = described_class.new
132
+ either_b = described_class.new
133
+ ty_string = TypedRb::Types::TyString.new
134
+ either_a[:return] = TypedRb::Types::TyStackJump.return(ty_string)
135
+
136
+ type_var = TypedRb::Types::TypingContext.local_type_variable
137
+ either_b[:return] = TypedRb::Types::TyStackJump.return(type_var)
138
+
139
+ before_constraints = TypedRb::Types::TypingContext.all_constraints.count
140
+ expect {
141
+ either_a.compatible_either?(either_b)
142
+ }.to_not raise_exception
143
+
144
+ after_constraints = TypedRb::Types::TypingContext.all_constraints.count
145
+ expect(after_constraints).to eq(before_constraints + 1)
146
+ expect(either_a[:return].wrapped_type.class).to eq(TypedRb::Types::Polymorphism::TypeVariable)
147
+ end
148
+
149
+ it 'adds constraints to type variables matching regular type_variables'do
150
+ either_a = described_class.new
151
+ either_b = described_class.new
152
+
153
+ type_var_a = TypedRb::Types::TypingContext.local_type_variable
154
+ either_a[:return] = TypedRb::Types::TyStackJump.return(type_var_a)
155
+
156
+ type_var_b = TypedRb::Types::TypingContext.local_type_variable
157
+ either_b[:return] = TypedRb::Types::TyStackJump.return(type_var_b)
158
+
159
+ before_constraints = TypedRb::Types::TypingContext.all_constraints.count
160
+ expect {
161
+ either_a.compatible_either?(either_b)
162
+ }.to_not raise_exception
163
+
164
+ after_constraints = TypedRb::Types::TypingContext.all_constraints.count
165
+ expect(after_constraints).to eq(before_constraints + 2)
166
+ expect(either_a[:return].wrapped_type.class).to eq(TypedRb::Types::Polymorphism::TypeVariable)
167
+ end
168
+
169
+ it 'type checks correctly types matching dynamic types' do
170
+ either_a = described_class.new
171
+ either_b = described_class.new
172
+
173
+ ty_string = TypedRb::Types::TyString.new
174
+ either_a[:return] = TypedRb::Types::TyStackJump.return(ty_string)
175
+
176
+ ty_dynamic = TypedRb::Types::TyDynamic.new(String)
177
+ either_b[:return] = TypedRb::Types::TyStackJump.return(ty_dynamic)
178
+
179
+ expect {
180
+ either_a.compatible_either?(either_b)
181
+ }.to_not raise_exception
182
+
183
+ expect(either_a[:return].wrapped_type.ruby_type).to eq(String)
184
+
185
+ # Reverse
186
+
187
+ either_a = described_class.new
188
+ either_b = described_class.new
189
+
190
+ ty_string = TypedRb::Types::TyString.new
191
+ either_a[:return] = TypedRb::Types::TyStackJump.return(ty_string)
192
+
193
+ ty_dynamic = TypedRb::Types::TyDynamic.new(String)
194
+ either_b[:return] = TypedRb::Types::TyStackJump.return(ty_dynamic)
195
+
196
+ expect {
197
+ either_b.compatible_either?(either_a)
198
+ }.to_not raise_exception
199
+
200
+ expect(either_b[:return].wrapped_type.ruby_type).to eq(String)
201
+ end
202
+
203
+ it 'type checks correctly types matching dynamic types' do
204
+ either_a = described_class.new
205
+ either_b = described_class.new
206
+
207
+ ty_string = TypedRb::Types::TyString.new
208
+ either_a[:return] = TypedRb::Types::TyStackJump.return(ty_string)
209
+
210
+ ty_unit = TypedRb::Types::TyUnit.new
211
+ either_b[:return] = TypedRb::Types::TyStackJump.return(ty_unit)
212
+
213
+ expect {
214
+ either_a.compatible_either?(either_b)
215
+ }.to_not raise_exception
216
+
217
+ expect(either_a[:return].wrapped_type.ruby_type).to eq(String)
218
+
219
+ # Reverse
220
+
221
+ either_a = described_class.new
222
+ either_b = described_class.new
223
+
224
+ ty_string = TypedRb::Types::TyString.new
225
+ either_b[:return] = TypedRb::Types::TyStackJump.return(ty_string)
226
+
227
+ ty_unit = TypedRb::Types::TyUnit.new
228
+ either_a[:return] = TypedRb::Types::TyStackJump.return(ty_unit)
229
+
230
+ expect {
231
+ either_a.compatible_either?(either_b)
232
+ }.to_not raise_exception
233
+
234
+ expect(either_a[:return].wrapped_type.ruby_type).to eq(String)
235
+ end
236
+ end
237
+ end
238
+
239
+ describe '.wrap/#unwrap' do
240
+
241
+ context 'with an either_type' do
242
+ it 'returns the same input either type' do
243
+ a = described_class.new
244
+ a[:normal] = TypedRb::Types::TyFloat.new
245
+ a[:return] = TypedRb::Types::TyStackJump.return(TypedRb::Types::TyFloat.new)
246
+ expect(described_class.wrap(a)).to eq(a)
247
+ expect(described_class.wrap(a).unwrap).to eq(a)
248
+ end
249
+ end
250
+
251
+ context 'with a normal type' do
252
+ it 'returns a wrapped either type' do
253
+ a = TypedRb::Types::TyFloat.new
254
+
255
+ either = described_class.wrap(a)
256
+ expect(either).to be_instance_of(described_class)
257
+ expect(either[:normal]).to eq(a)
258
+ expect(either.unwrap).to eq(a)
259
+ end
260
+ end
261
+
262
+ context 'with a stack jump' do
263
+ it 'returns a wrapped either type' do
264
+ a = TypedRb::Types::TyStackJump.return(TypedRb::Types::TyFloat.new)
265
+ either = described_class.wrap(a)
266
+ expect(either).to be_instance_of(described_class)
267
+ expect(either[:return]).to eq(a)
268
+ expect(either.unwrap).to eq(a)
269
+ end
270
+ end
271
+
272
+ context 'with no type wrapped' do
273
+ it 'returns the unit type' do
274
+ expect(described_class.new.unwrap.to_s).to eq('NilClass')
275
+ end
276
+ end
277
+ end
278
+
279
+ describe '#to_s' do
280
+ it 'displays a string for the type' do
281
+ a = described_class.new
282
+ a[:normal] = TypedRb::Types::TyFloat.new
283
+ a[:return] = TypedRb::Types::TyStackJump.return(TypedRb::Types::TyFloat.new)
284
+
285
+ expect(a.to_s).to eq('Either[normal:Float | return:Jump[return:Float]]')
286
+ end
287
+ end
288
+ end
@@ -0,0 +1,18 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Types::TyError do
4
+
5
+ describe '#to_s' do
6
+ it 'returns a string representation' do
7
+ expect(described_class.new.to_s).to eq('error')
8
+ end
9
+ end
10
+
11
+ describe '#compatible?' do
12
+ it 'is compatible with any type'do
13
+ expect(described_class.new.compatible?(nil)).to eq(true)
14
+ expect(described_class.new.compatible?(described_class.new)).to eq(true)
15
+ expect(described_class.new.compatible?(TypedRb::Types::TyObject.new(Object))).to eq(true)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,78 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Types::TyGenericObject do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ it 'instantiates correctly the concrete type from generic type' do
7
+
8
+ expr = <<__CODE
9
+ ts '#test_gen_inst_1 / String -> String'
10
+ def test_gen_inst_1(x); x; end
11
+
12
+ x = Array.(String).new
13
+ x << 'test'
14
+
15
+ test_gen_inst_1(x.at(0))
16
+ __CODE
17
+
18
+ result = language.check(expr)
19
+ expect(result.ruby_type).to eq(String)
20
+
21
+ expr = <<__CODE
22
+ ts '#test_gen_inst_2 / String -> String'
23
+ def test_gen_inst_2(x); x; end
24
+
25
+ x = Array.(Integer).new
26
+ x << 1
27
+
28
+ test_gen_inst_2(x.at(0))
29
+ __CODE
30
+
31
+ expect {
32
+ language.check(expr)
33
+ }.to raise_error(TypedRb::Types::UncomparableTypes,
34
+ /Cannot compare types Integer <=> String/)
35
+ end
36
+
37
+ it 'detects errors for the instantiated concrete type' do
38
+
39
+ expr = <<__CODE
40
+ x = Array.(Integer).new
41
+ x << 'string'
42
+ __CODE
43
+
44
+ expect {
45
+ language.check(expr)
46
+ }.to raise_error(TypedRb::Types::UncomparableTypes,/Cannot compare types String <=> Integer/)
47
+ end
48
+
49
+ it 'correctly types nested generic types' do
50
+ expr = <<__CODE
51
+ x = Array.('Array[Integer]').new
52
+ x << Array.(Integer).new
53
+ y = x.at(0)
54
+ y << 1
55
+ y.at(0)
56
+ __CODE
57
+
58
+ result = language.check(expr)
59
+ expect(result.ruby_type).to eq(Integer)
60
+ end
61
+
62
+ it 'detects errors in the types of nested generic types' do
63
+
64
+ expr = <<__CODE
65
+ x = Array.('Array[Integer]').new
66
+ x << Array.(String).new
67
+ y = x.at(0)
68
+ y << 1
69
+ y.at(0)
70
+ __CODE
71
+
72
+ expect {
73
+ language.check(expr)
74
+ }.to raise_error(TypedRb::Types::UncomparableTypes,
75
+ /Cannot compare types Array\[String\] <=> Array\[Integer\]/)
76
+
77
+ end
78
+ end