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