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,100 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmBooleanOperator do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ it 'type checks boolean operations of the same type' do
7
+ expr = 'true && false'
8
+
9
+ result = language.check(expr)
10
+ expect(result.ruby_type).to eq(TrueClass)
11
+
12
+ expr = 'true || false'
13
+
14
+ result = language.check(expr)
15
+ expect(result.ruby_type).to eq(TrueClass)
16
+
17
+ expr = 'true or false'
18
+
19
+ result = language.check(expr)
20
+ expect(result.ruby_type).to eq(TrueClass)
21
+
22
+ expr = 'true and false'
23
+
24
+ result = language.check(expr)
25
+ expect(result.ruby_type).to eq(TrueClass)
26
+ end
27
+
28
+ it 'type checks boolean operations with different types' do
29
+ expr = '1 && 0'
30
+
31
+ result = language.check(expr)
32
+ expect(result.ruby_type).to eq(Integer)
33
+
34
+ expr = '1 || Numeric.new'
35
+
36
+ result = language.check(expr)
37
+ expect(result.ruby_type).to eq(Numeric)
38
+
39
+ expr = '"string" or Numeric.new'
40
+
41
+ result = language.check(expr)
42
+ expect(result.ruby_type).to eq(Object)
43
+ end
44
+
45
+
46
+ it 'type checks boolean operations with nil values' do
47
+ expr = '1 && nil'
48
+
49
+ result = language.check(expr)
50
+ expect(result.ruby_type).to eq(Integer)
51
+
52
+ expr = 'nil || Numeric.new'
53
+
54
+ result = language.check(expr)
55
+ expect(result.ruby_type).to eq(Numeric)
56
+
57
+ expr = '"string" or nil'
58
+
59
+ result = language.check(expr)
60
+ expect(result.ruby_type).to eq(String)
61
+ end
62
+
63
+ it 'type checks operations with type variables' do
64
+
65
+ code = <<__CODE
66
+ class TBOp1
67
+ ts '#test / -> Boolean'
68
+ def test
69
+ @b || false
70
+ end
71
+
72
+ ts '#b / -> Boolean'
73
+ def b; @b; end
74
+ end
75
+
76
+ TBOp1.new.b
77
+ __CODE
78
+
79
+ result = language.check(code)
80
+ expect(result.ruby_type).to eq(TrueClass)
81
+
82
+
83
+ code = <<__CODE
84
+ class TBOp2
85
+ ts '#test / -> Boolean'
86
+ def test
87
+ @b || @c
88
+ end
89
+
90
+ ts '#b / -> Boolean'
91
+ def b; @b; end
92
+ end
93
+
94
+ TBOp2.new.b
95
+ __CODE
96
+
97
+ result = language.check(code)
98
+ expect(result.ruby_type).to eq(TrueClass)
99
+ end
100
+ end
@@ -0,0 +1,61 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmBoolean do
4
+
5
+ before :each do
6
+ ::BasicObject::TypeRegistry.clear
7
+ end
8
+
9
+ let(:typed_code) do
10
+ $TYPECHECK = true
11
+ eval(code, TOPLEVEL_BINDING)
12
+ ::BasicObject::TypeRegistry.normalize_types!
13
+ code
14
+ end
15
+
16
+ let(:ast) do
17
+ TypedRb::Model::GenSym.reset
18
+ parser = TypedRb::AstParser.new
19
+ parser.parse(typed_code)
20
+ end
21
+
22
+ context 'with validly typed code' do
23
+ let(:code) {
24
+ <<__CODE
25
+ ts '#f / Boolean -> Boolean'
26
+ def f(b)
27
+ b
28
+ end
29
+
30
+ f(true)
31
+ f(false)
32
+ __CODE
33
+ }
34
+
35
+ it 'should be possible to type check a method and method application' do
36
+ expect {
37
+ ast.check_type(TypedRb::Types::TypingContext.top_level)
38
+ }.to_not raise_error
39
+ end
40
+ end
41
+
42
+ context 'when used as a subtype' do
43
+ let(:code) {
44
+ <<__CODE
45
+ ts '#f / Object -> Object'
46
+ def f(b)
47
+ b
48
+ end
49
+
50
+ f(true)
51
+ f(false)
52
+ __CODE
53
+ }
54
+
55
+ it 'should be possible to type check method application' do
56
+ expect {
57
+ ast.check_type(TypedRb::Types::TypingContext.top_level)
58
+ }.to_not raise_error
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,28 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmConst do
4
+
5
+ let(:language) { TypedRb::Language.new }
6
+
7
+ it 'type checks class constants' do
8
+ result = language.check('class TmConstTest1; end; TmConstTest1')
9
+ expect(result.ruby_type).to eq(TmConstTest1)
10
+ end
11
+
12
+ it 'type checks module constants' do
13
+ result = language.check('module TmConstTest2; end; TmConstTest2')
14
+ expect(result.ruby_type).to eq(TmConstTest2)
15
+ end
16
+
17
+ it 'type checks user defined constants' do
18
+ code = <<__END
19
+ module TestConstTest3
20
+ MY_CONSTANT = 2
21
+ end
22
+
23
+ TestConstTest3::MY_CONSTANT
24
+ __END
25
+ result = language.check(code)
26
+ expect(result.ruby_type).to eq(Fixnum)
27
+ end
28
+ end
@@ -0,0 +1,12 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmDefined do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ it 'defined invocations' do
7
+ expr = 'defined? 2'
8
+
9
+ result = language.check(expr)
10
+ expect(result.ruby_type).to eq(String)
11
+ end
12
+ end
@@ -0,0 +1,347 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmFun do
4
+ before :each do
5
+ ::BasicObject::TypeRegistry.clear
6
+ end
7
+
8
+ let(:code) do
9
+ text = <<__CODE
10
+ class A
11
+ ts '#f1 / Integer -> String'
12
+ def f1(num)
13
+ 'String'
14
+ end
15
+
16
+ ts '#f2 / Integer -> String'
17
+ def f2(num=2)
18
+ f1(num)
19
+ end
20
+ end
21
+ __CODE
22
+ text
23
+ end
24
+
25
+ let(:typed_code) do
26
+ $TYPECHECK = true
27
+ eval(code, TOPLEVEL_BINDING)
28
+ ::BasicObject::TypeRegistry.normalize_types!
29
+ code
30
+ end
31
+
32
+ let(:ast) do
33
+ TypedRb::Model::GenSym.reset
34
+ parser = TypedRb::AstParser.new
35
+ parser.parse(typed_code)
36
+ end
37
+
38
+ context 'with validly typed code' do
39
+ it 'is possible to type check a method and method application' do
40
+ expect do
41
+ ast.check_type(TypedRb::Types::TypingContext.new)
42
+ end.to_not raise_error
43
+ end
44
+ end
45
+
46
+ context 'with not matching arg type in function definition' do
47
+ let(:code) do
48
+ text = <<__CODE
49
+ class A
50
+ ts '#f1 / Integer -> String'
51
+ def f1(num='text')
52
+ 'String'
53
+ end
54
+
55
+ ts '#f2 / Integer -> String'
56
+ def f2(num)
57
+ f1(num)
58
+ end
59
+ end
60
+ __CODE
61
+ text
62
+ end
63
+
64
+ it 'raises a type error' do
65
+ expect do
66
+ ast.check_type(TypedRb::Types::TypingContext.new)
67
+ end.to raise_error(TypedRb::Types::UncomparableTypes)
68
+ end
69
+ end
70
+
71
+ context 'with not matching return type in function definition' do
72
+ let(:code) do
73
+ text =<<__CODE
74
+ class A
75
+ ts '#f1 / Integer -> String'
76
+ def f1(num)
77
+ 2
78
+ end
79
+
80
+ ts '#f2 / Integer -> String'
81
+ def f2(num)
82
+ f1(num)
83
+ end
84
+ end
85
+ __CODE
86
+ text
87
+ end
88
+
89
+ it 'raises a type error' do
90
+ expect do
91
+ ast.check_type(TypedRb::Types::TypingContext.new)
92
+ end.to raise_error(TypedRb::Types::UncomparableTypes)
93
+ end
94
+ end
95
+
96
+ context 'with application without optional arguments' do
97
+ let(:code) do
98
+ text = <<__CODE
99
+ ts '#f / Integer -> Integer -> String'
100
+ def f(a,b=1)
101
+ 'string'
102
+ end
103
+
104
+ f(2)
105
+
106
+ f(2,3)
107
+ __CODE
108
+ text
109
+ end
110
+
111
+ it 'does not raise a type error' do
112
+ expect do
113
+ ast.check_type(TypedRb::Types::TypingContext.top_level)
114
+ end.not_to raise_error
115
+ end
116
+ end
117
+
118
+ context 'with application without erroneus optional arguments' do
119
+ let(:code) do
120
+ text = <<__CODE
121
+ ts '#f / Integer -> Integer -> String'
122
+ def f(a,b='string')
123
+ 'string'
124
+ end
125
+
126
+ f(2)
127
+
128
+ f(2,3)
129
+ __CODE
130
+ text
131
+ end
132
+
133
+ it 'does not raise a type error' do
134
+ expect do
135
+ ast.check_type(TypedRb::Types::TypingContext.top_level)
136
+ end.to raise_error(TypedRb::Types::UncomparableTypes)
137
+ end
138
+ end
139
+
140
+ context 'with application with rest args' do
141
+
142
+ context 'with correct types' do
143
+ let(:code) do
144
+ text = <<__CODE
145
+ ts 'type Array[T]'
146
+
147
+ ts '#f / Integer -> Integer... -> String'
148
+ def f(a, *b)
149
+ 'string'
150
+ end
151
+
152
+ f(2, 3, 4, 5)
153
+ __CODE
154
+ text
155
+ end
156
+
157
+ it 'doest not raise a type error' do
158
+
159
+ expect do
160
+ res = ast.check_type(TypedRb::Types::TypingContext.top_level)
161
+ expect(res.ruby_type).to eq(String)
162
+ end.not_to raise_error
163
+ end
164
+ end
165
+
166
+ context 'with erroneous types' do
167
+ let(:code) do
168
+ text = <<__CODE
169
+ ts 'type Array[T]'
170
+
171
+ ts '#f / Integer -> Integer... -> String'
172
+ def f(a, *b)
173
+ 'string'
174
+ end
175
+
176
+ f(2, 'a', 'b')
177
+ __CODE
178
+ text
179
+ end
180
+
181
+ it 'raises a type error' do
182
+
183
+ expect do
184
+ ast.check_type(TypedRb::Types::TypingContext.top_level)
185
+ end.to raise_error(TypedRb::TypeCheckError)
186
+ end
187
+ end
188
+
189
+ context 'with missing rest args' do
190
+ let(:code) do
191
+ text = <<__CODE
192
+ ts 'type Array[T]'
193
+
194
+ ts '#f / Integer -> Integer... -> String'
195
+ def f(a, *b)
196
+ 'string'
197
+ end
198
+
199
+ f(2)
200
+ __CODE
201
+ text
202
+ end
203
+
204
+ it 'does not raise a type error' do
205
+
206
+ expect do
207
+ res = ast.check_type(TypedRb::Types::TypingContext.top_level)
208
+ expect(res.ruby_type).to eq(String)
209
+ end.not_to raise_error
210
+ end
211
+ end
212
+
213
+ context 'with a correctly typed class function' do
214
+ let(:code) do
215
+ text = <<__CODE
216
+ class CFA
217
+ ts '.a / String -> Integer'
218
+ def self.a(x); 1; end
219
+ end
220
+
221
+ CFA.a('string')
222
+ __CODE
223
+ end
224
+
225
+ it 'does not raise a type error' do
226
+ res = ast.check_type(TypedRb::Types::TypingContext.top_level)
227
+ expect(res.ruby_type).to eq(Integer)
228
+ end
229
+ end
230
+
231
+ context 'with a correctly typed class function added to the class object' do
232
+ let(:code) do
233
+ text = <<__CODE
234
+ class CFB; end
235
+
236
+ ts 'CFB.b / String -> Integer'
237
+ def CFB.b(x); 1; end
238
+
239
+
240
+ CFB.b('string')
241
+ __CODE
242
+ end
243
+
244
+ it 'does not raise a type error' do
245
+ res = ast.check_type(TypedRb::Types::TypingContext.top_level)
246
+ expect(res.ruby_type).to eq(Integer)
247
+ end
248
+ end
249
+
250
+ context 'with a mistmacth in the arg types' do
251
+ context 'with an untyped function' do
252
+ let(:code) do
253
+ text = <<__CODE
254
+ class CFC1
255
+ ts '#t / String -> Integer'
256
+ def t(x); 1; end
257
+ end
258
+
259
+ class CFC2 < CFC1
260
+ def t; 1; end
261
+ end
262
+ CFC2.new.t
263
+ __CODE
264
+ end
265
+ it 'does not raise an error' do
266
+ expect do
267
+ ast.check_type(TypedRb::Types::TypingContext.top_level)
268
+ end.not_to raise_error
269
+ end
270
+ end
271
+
272
+ context 'with a typed function' do
273
+ let(:code) do
274
+ text = <<__CODE
275
+ class CFD
276
+ ts '#t / String -> Integer'
277
+ def t(x); 1; end
278
+ end
279
+ __CODE
280
+ end
281
+ it 'does raises an error' do
282
+ expect do
283
+ ast.check_type(TypedRb::Types::TypingContext.top_level)
284
+ end.not_to raise_error
285
+ end
286
+ end
287
+
288
+ context 'with a missing block arg' do
289
+ let(:code) do
290
+ text = <<__CODE
291
+ class CFE
292
+ ts '#t / String -> Integer'
293
+ def t(x, &b); 1; end
294
+ end
295
+ __CODE
296
+ end
297
+ it 'does raises an error' do
298
+ expect do
299
+ ast.check_type(TypedRb::Types::TypingContext.top_level)
300
+ end.to raise_error(TypedRb::TypeCheckError)
301
+ end
302
+ end
303
+ end
304
+ end
305
+
306
+ context 'with a either conditional return, positive case' do
307
+ let(:code) do
308
+ <<__CODE
309
+ ts '#t / String -> Integer'
310
+ def t(s)
311
+ if s == 'foo'
312
+ 0
313
+ else
314
+ return 1
315
+ end
316
+ end
317
+ t('bar')
318
+ __CODE
319
+ end
320
+
321
+ it 'does not raise an error' do
322
+ result = ast.check_type(TypedRb::Types::TypingContext.top_level)
323
+ expect(result.ruby_type).to eq(Integer)
324
+ end
325
+ end
326
+
327
+ context 'with a either conditional return, negative case' do
328
+ let(:code) do
329
+ <<__CODE
330
+ ts '#t / String -> Integer'
331
+ def t(s)
332
+ if s == 'foo'
333
+ 0
334
+ else
335
+ return 'bar'
336
+ end
337
+ end
338
+ __CODE
339
+ end
340
+
341
+ it 'does not raise an error' do
342
+ expect {
343
+ ast.check_type(TypedRb::Types::TypingContext.top_level)
344
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
345
+ end
346
+ end
347
+ end
@@ -0,0 +1,33 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmGlobalVar do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ context 'with a valid global var' do
7
+ it 'is possible to type-check the global var' do
8
+ expr = <<__END
9
+ $test = 1
10
+ $test
11
+ __END
12
+
13
+ result = language.check(expr)
14
+ expect(result.bound.ruby_type).to eq(Integer)
15
+ end
16
+
17
+ it 'is possible to type-check errors in global var typing' do
18
+ expr = <<__END
19
+ $test = 1
20
+ $test = 'test'
21
+
22
+ ts '#x / Integer -> unit'
23
+ def x(n); end
24
+
25
+ x($test)
26
+ __END
27
+
28
+ expect {
29
+ language.check(expr)
30
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,104 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmIfElse do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ it 'types correctly if/then/else branches' do
7
+ expr = <<__CODE
8
+ if true
9
+ 1
10
+ else
11
+ 2
12
+ end
13
+ __CODE
14
+
15
+ result = language.check(expr)
16
+ expect(result).to eq(tyinteger)
17
+ end
18
+
19
+ it 'types correctly if/then' do
20
+ expr = <<__CODE
21
+ 1 if true
22
+ __CODE
23
+
24
+ result = language.check(expr)
25
+ expect(result).to eq(tyinteger)
26
+ end
27
+
28
+ it 'types correctly if/else' do
29
+ expr = <<__CODE
30
+ 1 unless true
31
+ __CODE
32
+ result = language.check(expr)
33
+ expect(result).to eq(tyinteger)
34
+ end
35
+
36
+ it 'types correctly return statements in if/then/else branches' do
37
+ expr = <<__CODE
38
+ ts '#fbite1 / -> Integer'
39
+ def fbite1
40
+ return 1 if true
41
+ end
42
+ fbite1
43
+ __CODE
44
+
45
+ result = language.check(expr)
46
+ expect(result).to eq(tyinteger)
47
+ end
48
+
49
+ it 'types correctly return statements in if/then branches' do
50
+ expr = <<__CODE
51
+ ts '#fbite2 / -> Integer'
52
+ def fbite2
53
+ return 2 unless true
54
+ end
55
+ fbite2
56
+ __CODE
57
+
58
+ result = language.check(expr)
59
+ expect(result).to eq(tyinteger)
60
+ end
61
+
62
+ it 'types correctly return statements in if/else branches' do
63
+ expr = <<__CODE
64
+ ts '#fbite3 / -> Integer'
65
+ def fbite3
66
+ if true
67
+ return 1
68
+ else
69
+ return 2
70
+ end
71
+ end
72
+ fbite3
73
+ __CODE
74
+
75
+ result = language.check(expr)
76
+ expect(result).to eq(tyinteger)
77
+ end
78
+
79
+ it 'types correctly if/then/else statements with errors in the then branch' do
80
+ expr = <<__CODE
81
+ if false
82
+ fail StandardError, 'error'
83
+ else
84
+ 1
85
+ end
86
+ __CODE
87
+
88
+ result = language.check(expr)
89
+ expect(result.ruby_type).to eq(Integer)
90
+ end
91
+
92
+ it 'types correctly if/then/else statements with errors in the else branch' do
93
+ expr = <<__CODE
94
+ if true
95
+ 1
96
+ else
97
+ fail StandardError, 'error'
98
+ end
99
+ __CODE
100
+
101
+ result = language.check(expr)
102
+ expect(result.ruby_type).to eq(Integer)
103
+ end
104
+ end
@@ -0,0 +1,24 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe BasicObject do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ it 'Ignores functions marked with #ts_ignore' do
7
+ expr = <<__CODE
8
+ class TypeA
9
+
10
+ ts '#fa / -> String'
11
+ ts_ignore
12
+ def fa
13
+ 2.0
14
+ end
15
+
16
+ end
17
+
18
+ TypeA.new.fa
19
+ __CODE
20
+
21
+ result = language.check(expr)
22
+ expect(result.to_s).to eq('String')
23
+ end
24
+ end