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,79 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe ':break term' do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ it 'is type checked correctly, positive case' do
7
+ code = <<__END
8
+ ts '#test_break / Integer -> &(Integer -> unit) -> Integer'
9
+ def test_break(x)
10
+ yield(x)
11
+ end
12
+
13
+ test_break(0) { |x| break(1) }
14
+ __END
15
+
16
+ result = language.check(code)
17
+ expect(result.to_s).to eq('Integer')
18
+ end
19
+
20
+ it 'is type checked correctly, no break value, positive case' do
21
+ code = <<__END
22
+ ts '#test_break / Integer -> &(Integer -> unit) -> Integer'
23
+ def test_break(x)
24
+ yield(x)
25
+ end
26
+
27
+ test_break(0) { |x| break }
28
+ __END
29
+
30
+ result = language.check(code)
31
+ expect(result.to_s).to eq('Integer')
32
+ end
33
+
34
+ it 'is type checked correctly, negative case' do
35
+ code = <<__END
36
+ ts '#test_break / Integer -> &(Integer -> unit) -> Integer'
37
+ def test_break(x)
38
+ yield(x)
39
+ end
40
+
41
+ test_break(0) { |x| break("") }
42
+ __END
43
+
44
+ expect {
45
+ language.check(code)
46
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
47
+ end
48
+
49
+ context 'with not matching return type' do
50
+ it 'is type checked correctly, positive case' do
51
+ code = <<__END
52
+ ts '#test_break / Integer -> &(Integer -> Integer) -> Integer'
53
+ def test_break(x)
54
+ yield(x)
55
+ end
56
+
57
+ test_break(0) { |x| break(1) }
58
+ __END
59
+
60
+ result = language.check(code)
61
+ expect(result.to_s).to eq('Integer')
62
+ end
63
+
64
+ it 'is type checked correctly, negative case' do
65
+ code = <<__END
66
+ ts '#test_break / Integer -> &(String -> Integer) -> Integer'
67
+ def test_break(x)
68
+ yield(x)
69
+ end
70
+
71
+ test_break(0) { |x| break(1) }
72
+ __END
73
+
74
+ expect {
75
+ language.check(code)
76
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,191 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe 'generics use caes' do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ it 'applies arguments to generic types' do
7
+ code = <<__END
8
+ ts 'type TestGen1[T]'
9
+ class TestGen1
10
+ ts '#gm / [T] -> [T]'
11
+ def gm(t)
12
+ t
13
+ end
14
+ end
15
+
16
+ TestGen1.(String).new.gm('string')
17
+ __END
18
+ result = language.check(code)
19
+ expect(result.ruby_type).to eq(String)
20
+
21
+ code = <<__END
22
+ ts 'type TestGen1[T]'
23
+ class TestGen1
24
+ ts '#gm / [T] -> &([T] -> [T]) -> [T]'
25
+ def gm(t)
26
+ yield t
27
+ end
28
+ end
29
+
30
+ TestGen1.(String).new.gm('string') { |t| 'string' }
31
+ __END
32
+ result = language.check(code)
33
+ expect(result.ruby_type).to eq(String)
34
+
35
+ code = <<__END
36
+ ts 'type TestGen1[T]'
37
+ class TestGen1
38
+ ts '#gm / [T] -> &([T] -> [T]) -> [T]'
39
+ def gm(t)
40
+ yield t
41
+ end
42
+ end
43
+
44
+ TestGen1.(String).new.gm('string') { |t| 2 }
45
+ __END
46
+
47
+ expect do
48
+ language.check(code)
49
+ end.to raise_error(TypedRb::TypeCheckError)
50
+ end
51
+
52
+
53
+ it 'applies arguments to generic types without implementation' do
54
+ code = <<__END
55
+ xs = Array.(String).new
56
+ xs << 'string'
57
+ xs.at(0)
58
+ __END
59
+ result = language.check(code)
60
+ expect(result.ruby_type).to eq(String)
61
+
62
+ code = <<__END
63
+ xs = Array.(String).new
64
+ xs << 2
65
+ xs.at(0)
66
+ __END
67
+
68
+ expect do
69
+ language.check(code)
70
+ end.to raise_error(TypedRb::TypeCheckError)
71
+ end
72
+
73
+ it 'materializes generic types using type variables' do
74
+ code = <<__END
75
+ ts 'type TestGen2[T]'
76
+ class TestGen2
77
+
78
+ ts '#gm / [T] -> Array[T]'
79
+ def gm(x)
80
+ xs = Array.('[T]').new
81
+ xs << x
82
+ xs
83
+ end
84
+ end
85
+
86
+ TestGen2.(String).new.gm('x')
87
+ __END
88
+
89
+ result = language.check(code)
90
+ expect(result.to_s).to eq('Array[String]')
91
+ end
92
+
93
+ it 'detects errors materializing generic types using type variables' do
94
+ code = <<__END
95
+ ts 'type TestGen2[T][U]'
96
+ class TestGen2
97
+
98
+ ts '#gm / [T] -> [U] -> Array[T]'
99
+ def gm(x,y)
100
+ xs = Array.('[T]').new
101
+ xs << y
102
+ xs
103
+ end
104
+ end
105
+
106
+ TestGen2.(String,Integer).new.gm('x',2)
107
+ __END
108
+
109
+ expect do
110
+ language.check(code)
111
+ end.to raise_error(TypedRb::TypeCheckError,
112
+ /TestGen2\:T\:\:\[\?,\?\] expected, TestGen2\:U\:\:\[\?,\?\]/)
113
+ end
114
+
115
+ it 'type-checks correctly super type generics' do
116
+ code = <<__END
117
+ class Array
118
+ ts '#last / Integer... -> [T]'
119
+ end
120
+
121
+ ts 'type MyContainerG1[T] super Array[Object]'
122
+ class MyContainerG1 < Array
123
+ ts '#first / -> [T]'
124
+ end
125
+
126
+ MyContainerG1.(String).new.last
127
+ __END
128
+
129
+ result = language.check(code)
130
+ expect(result.ruby_type).to eq(Object)
131
+ end
132
+
133
+ it 'type-checks correctly super type generics detecting type errors based on the super-type parameter' do
134
+ code = <<__END
135
+ ts 'type BaseGen1[T]'
136
+ class BaseGen1
137
+ ts '#getString / -> String'
138
+ def getString
139
+ 'a string'
140
+ end
141
+
142
+ ts '#in_subclass / -> [T]'
143
+ def in_subclass
144
+ getString
145
+ end
146
+ end
147
+
148
+ ts 'type MyContainerG2[T] super BaseGen1[String]'
149
+ class MyContainerG2 < BaseGen1
150
+ end
151
+
152
+ ts 'type MyContainerG3[T] super BaseGen1[Integer]'
153
+ class MyContainerG3 < BaseGen1
154
+ end
155
+ __END
156
+
157
+ expect do
158
+ language.check(code)
159
+ end.to raise_error(TypedRb::Types::UncomparableTypes,
160
+ /Cannot compare types Object with.*Integer/)
161
+ end
162
+
163
+ it 'type-checks correctly super type generics detecting type errors based on the super-type parameter on type instantiation' do
164
+ code = <<__END
165
+ ts 'type BaseGen2[T]'
166
+ class BaseGen2
167
+ ts '#getString / -> String'
168
+ def getString
169
+ 'a string'
170
+ end
171
+
172
+ ts '#in_subclass / -> [T]'
173
+ def in_subclass
174
+ getString
175
+ end
176
+ end
177
+
178
+ ts 'type MyContainerG4[T] super BaseGen2[T]'
179
+ class MyContainerG4 < BaseGen2
180
+ end
181
+ BaseGen2.(String).new
182
+ MyContainerG4.(Integer).new
183
+ __END
184
+
185
+ expect do
186
+ language.check(code)
187
+ end.to raise_error(TypedRb::Types::UncomparableTypes,
188
+ /Cannot compare types Object with.*Integer/)
189
+ end
190
+
191
+ end
@@ -0,0 +1,103 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe 'instance vars' do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ it 'types correctly instance vars, case 1' do
7
+ code = <<__END
8
+ class TestIVar
9
+
10
+ ts '#gm1 / -> Integer'
11
+ def gm1
12
+ @a = 1
13
+ end
14
+
15
+ ts '#gm2 / -> String'
16
+ def gm2
17
+ @a = 'hey'
18
+ 'hey'
19
+ end
20
+
21
+ ts '#gm3 / -> Object'
22
+ def gm3
23
+ @a
24
+ end
25
+ end
26
+ __END
27
+
28
+ language.check(code)
29
+ end
30
+
31
+ it 'types correctly instance vars, positive case 2' do
32
+ code = <<__END
33
+ class TestIVar
34
+
35
+ ts '#gm1 / -> Integer'
36
+ def gm1
37
+ @a = 1
38
+ end
39
+
40
+ ts '#gm2 / -> String'
41
+ def gm2
42
+ @a = 'hey'
43
+ 'hey'
44
+ end
45
+
46
+ ts '#gm3 / -> Float'
47
+ def gm3
48
+ @a
49
+ end
50
+ end
51
+ __END
52
+
53
+ expect {
54
+ language.check(code)
55
+ }.to raise_error(TypedRb::Types::Polymorphism::UnificationError)
56
+ end
57
+
58
+ it 'types correctly instance vars, positive case 3' do
59
+ code = <<__END
60
+ class TestIVar
61
+
62
+ ts '#gm1 / -> Integer'
63
+ def gm1
64
+ @a = 1
65
+ end
66
+
67
+ ts '#gm2 / -> String'
68
+ def gm2
69
+ @a = 'hey'
70
+ 'hey'
71
+ end
72
+ end
73
+ __END
74
+
75
+ expect {
76
+ language.check(code)
77
+ }.not_to raise_error
78
+ end
79
+
80
+
81
+ it 'types correctly instance vars, positive case 5' do
82
+ code = <<__END
83
+ class TestIVar5
84
+ ts '#gm1 / -> Integer'
85
+ def gm1
86
+ @a = 1
87
+ end
88
+ end
89
+
90
+ class TestIVar5
91
+ ts '#gm2 / -> String'
92
+ def gm2
93
+ @a = 'hey'
94
+ @a
95
+ end
96
+ end
97
+ __END
98
+
99
+ expect {
100
+ language.check(code)
101
+ }.to raise_error
102
+ end
103
+ end
@@ -0,0 +1,29 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe ':next term' do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ it 'is type checked correctly, positive case' do
7
+ code = <<__END
8
+ [1,2,3,4].map { |i| next(i * 2) }
9
+ __END
10
+
11
+ result = language.check(code)
12
+ expect(result.to_s).to eq('Array[Integer]')
13
+ end
14
+
15
+ it 'is type checked correctly, negative case' do
16
+ code = <<__END
17
+ ts '#test_break / Integer -> &(Integer -> Integer) -> Integer'
18
+ def test_break(x)
19
+ yield(x)
20
+ end
21
+
22
+ test_break(0) { |x| next("") }
23
+ __END
24
+
25
+ expect {
26
+ language.check(code)
27
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
28
+ end
29
+ end
@@ -0,0 +1,104 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe 'operator assign operations' do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ context 'with a local variable' do
7
+ it 'type checks assignment operations over local variables, positive case' do
8
+ expr = <<__CODE
9
+ a = 0
10
+ a += 1
11
+ __CODE
12
+
13
+ result = language.check(expr)
14
+ expect(result.ruby_type).to eq(Integer)
15
+ end
16
+
17
+ it 'type checks assignment operations over local variables, negative case' do
18
+ expr = <<__CODE
19
+ class LocalVarTest
20
+ ts '#+ / LocalVarTest -> LocalVarTest'
21
+ def +(other)
22
+ self
23
+ end
24
+ end
25
+
26
+ ts '#x / -> LocalVarTest'
27
+ def x
28
+ a = LocalVarTest.new
29
+ a += 1
30
+ end
31
+ __CODE
32
+
33
+ expect {
34
+ language.check(expr)
35
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
36
+ end
37
+ end
38
+
39
+ context 'with an instance variable' do
40
+ it 'type checks assignment operations over instance variables, positive case' do
41
+ expr = <<__CODE
42
+ @a = 0
43
+ @a += 1
44
+ __CODE
45
+ result = language.check(expr)
46
+ expect(result.bound.ruby_type).to eq(Integer)
47
+ end
48
+
49
+ it 'type checks assignment operations over instance variables, negative case' do
50
+ expr = <<__CODE
51
+ class LocalVarTest
52
+ ts '#+ / LocalVarTest -> LocalVarTest'
53
+ def +(other)
54
+ self
55
+ end
56
+ end
57
+
58
+ ts '#x / -> LocalVarTest'
59
+ def x
60
+ @a = LocalVarTest.new
61
+ @a += 1
62
+ end
63
+ __CODE
64
+
65
+ expect {
66
+ language.check(expr)
67
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
68
+ end
69
+ end
70
+
71
+ context 'with a global variable' do
72
+ it 'type checks assignment operations over global variables, positive case' do
73
+ expr = <<__CODE
74
+ $TEST_GLOBAL_OPS = 0
75
+ $TEST_GLOBAL_OPS += 1
76
+ __CODE
77
+ result = language.check(expr)
78
+ expect(result.bound.ruby_type).to eq(Integer)
79
+ end
80
+ end
81
+
82
+ context 'with a constant' do
83
+ it 'type checks assignment operations over global variables, positive case' do
84
+ expr = <<__CODE
85
+ TEST_GLOBAL_OPS = 0
86
+ TEST_GLOBAL_OPS += 1
87
+ __CODE
88
+ result = language.check(expr)
89
+ expect(result.ruby_type).to eq(Integer)
90
+ end
91
+ end
92
+
93
+ context 'with a message sent as the receiver' do
94
+ it 'type checks assignment operations over sending of messages, positive case' do
95
+ expr = <<__CODE
96
+ a = [1]
97
+ a[0] += 2
98
+ __CODE
99
+
100
+ result = language.check(expr)
101
+ expect(result.ruby_type).to eq(Object)
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,31 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmSend do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ context 'with a function with multiple type signatures' do
7
+ it 'type checks methods with multiple type signatures' do
8
+ eval('class TOM1; def f(a, *args, &b); end; end')
9
+
10
+ base = <<__CODE
11
+ class TOM1
12
+ ts '#f / String -> Integer'
13
+ ts '#f / String -> Integer -> String'
14
+ end
15
+
16
+ __CODE
17
+
18
+ expr1 = "#{base}TOM1.new.f('a')"
19
+ result = language.check(expr1)
20
+ expect(result).to eq(tyinteger)
21
+
22
+ expr2 = "#{base}TOM1.new.f('a', 2)"
23
+ result = language.check(expr2)
24
+ expect(result).to eq(tystring)
25
+
26
+ expr3 = "#{base}TOM1.new.f('a', 2, nil)"
27
+ result = language.check(expr3)
28
+ expect(result).to eq(tydynamic)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,112 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Types::Type do
4
+ before :each do
5
+ ::BasicObject::TypeRegistry.clear
6
+ end
7
+
8
+ let(:typed_code) do
9
+ $TYPECHECK = true
10
+ eval(code, TOPLEVEL_BINDING)
11
+ ::BasicObject::TypeRegistry.normalize_types!
12
+ code
13
+ end
14
+
15
+ let(:ast) do
16
+ TypedRb::Model::GenSym.reset
17
+ parser = TypedRb::AstParser.new
18
+ parser.parse(typed_code)
19
+ end
20
+
21
+ context 'with valid exact type' do
22
+ let(:code) do
23
+ text = <<__CODE
24
+ ts '#test / Integer -> Integer'
25
+ def test(x)
26
+ x
27
+ end
28
+ __CODE
29
+ text
30
+ end
31
+
32
+ it 'should not raise a type error' do
33
+ expect do
34
+ ast.check_type(TypedRb::Types::TypingContext.top_level)
35
+ end.to_not raise_error
36
+ end
37
+ end
38
+
39
+ context 'with a super-type class' do
40
+ let(:code) do
41
+ text = <<__CODE
42
+ ts '#test / Integer -> Numeric'
43
+ def test(x)
44
+ x
45
+ end
46
+ __CODE
47
+ text
48
+ end
49
+
50
+ it 'should not raise a type error' do
51
+ expect do
52
+ ast.check_type(TypedRb::Types::TypingContext.top_level)
53
+ end.to_not raise_error
54
+ end
55
+ end
56
+
57
+ context 'with a super-type argument' do
58
+ let(:code) do
59
+ text = <<__CODE
60
+ ts '#test / Numeric -> Numeric'
61
+ def test(x)
62
+ x
63
+ end
64
+
65
+ test(1)
66
+ __CODE
67
+ text
68
+ end
69
+
70
+ it 'should not raise a type error' do
71
+ expect {
72
+ ast.check_type(TypedRb::Types::TypingContext.top_level)
73
+ }.to_not raise_error
74
+ end
75
+ end
76
+
77
+ context 'with a sub-type class' do
78
+ let(:code) do
79
+ text = <<__CODE
80
+ ts '#test / Numeric -> Integer'
81
+ def test(x)
82
+ x
83
+ end
84
+ __CODE
85
+ text
86
+ end
87
+
88
+ it 'should raise a type error' do
89
+ expect {
90
+ ast.check_type(TypedRb::Types::TypingContext.top_level)
91
+ }.to raise_error(TypedRb::TypeCheckError)
92
+ end
93
+ end
94
+
95
+ context 'with a sub-type optional argument' do
96
+ let(:code) do
97
+ text = <<__CODE
98
+ ts '#test / Numeric -> Numeric'
99
+ def test(x = 1)
100
+ x
101
+ end
102
+ __CODE
103
+ text
104
+ end
105
+
106
+ it 'should not raise a type error' do
107
+ expect do
108
+ ast.check_type(TypedRb::Types::TypingContext.top_level)
109
+ end.to_not raise_error
110
+ end
111
+ end
112
+ end