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,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