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,117 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmInstanceVar do
4
+
5
+ before :each do
6
+ ::BasicObject::TypeRegistry.clear
7
+ end
8
+
9
+ let(:code) do
10
+ text =<<__CODE
11
+ class A
12
+ ts '\#@a / Integer'
13
+ ts '#initialize / -> unit'
14
+ def initialize
15
+ @a = 'error'
16
+ end
17
+ end
18
+ __CODE
19
+ text
20
+ end
21
+
22
+ let(:typed_code) do
23
+ $TYPECHECK = true
24
+ eval(code, TOPLEVEL_BINDING)
25
+ ::BasicObject::TypeRegistry.normalize_types!
26
+ code
27
+ end
28
+
29
+ let(:ast) do
30
+ TypedRb::Model::GenSym.reset
31
+ parser = TypedRb::AstParser.new
32
+ parser.parse(typed_code)
33
+ end
34
+
35
+ context 'with invalid type assignment' do
36
+ it 'should raise a type error' do
37
+ expect {
38
+ ast.check_type(TypedRb::Types::TypingContext.new)
39
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
40
+ end
41
+ end
42
+
43
+ context 'with valid type assignment' do
44
+ let(:code) do
45
+ text =<<__CODE
46
+ class A
47
+ ts '\#@a / Integer'
48
+
49
+ ts '#initialize / -> unit'
50
+ def initialize
51
+ @a = 10
52
+ a(@a)
53
+ end
54
+
55
+ ts '#a / Integer -> Integer'
56
+ def a(x)
57
+ x
58
+ end
59
+ end
60
+ __CODE
61
+ text
62
+ end
63
+
64
+ it 'should not raise a type error' do
65
+ expect {
66
+ ast.check_type(TypedRb::Types::TypingContext.new)
67
+ }.to_not raise_error
68
+ end
69
+ end
70
+
71
+ context 'with a valid singleton class instance variable' do
72
+ let(:code) do
73
+ <<__CODE
74
+ class A
75
+ ts '.@a / Integer'
76
+
77
+ ts 'A.a / -> Integer'
78
+ def self.a
79
+ @a
80
+ end
81
+ end
82
+
83
+ A.a
84
+ __CODE
85
+ end
86
+
87
+ it 'should not raise a type error' do
88
+ expect {
89
+ result = ast.check_type(TypedRb::Types::TypingContext.new)
90
+ expect(result.to_s).to eq('Integer')
91
+ }.to_not raise_error
92
+ end
93
+ end
94
+
95
+ context 'with an invalid type annotation' do
96
+ let(:code) do
97
+ <<__CODE
98
+ class A
99
+ ts '.@a / Integer'
100
+
101
+ ts 'A.a / -> String'
102
+ def self.a
103
+ @a
104
+ end
105
+ end
106
+
107
+ A.a
108
+ __CODE
109
+ end
110
+
111
+ it 'should raise a type error' do
112
+ expect {
113
+ result = ast.check_type(TypedRb::Types::TypingContext.new)
114
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,134 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmLocalVarAsgn do
4
+ before :each do
5
+ ::BasicObject::TypeRegistry.clear
6
+ end
7
+
8
+ let(:code) do
9
+ text =<<__CODE
10
+ a = 3
11
+ a
12
+ __CODE
13
+ text
14
+ end
15
+
16
+ let(:typed_code) do
17
+ $TYPECHECK = true
18
+ eval(code, TOPLEVEL_BINDING)
19
+ ::BasicObject::TypeRegistry.normalize_types!
20
+ code
21
+ end
22
+
23
+ let(:ast) do
24
+ TypedRb::Model::GenSym.reset
25
+ parser = TypedRb::AstParser.new
26
+ parser.parse(typed_code)
27
+ end
28
+
29
+ context 'with simple assignment' do
30
+ it 'should be possible to get the right type' do
31
+ type = ast.check_type(TypedRb::Types::TypingContext.top_level)
32
+ expect(type.to_s).to eq('Integer')
33
+ end
34
+ end
35
+
36
+
37
+ context 'with variable assignment' do
38
+ let(:code) do
39
+ text =<<__CODE
40
+ a = 3
41
+ b = a
42
+ b
43
+ __CODE
44
+ text
45
+ end
46
+
47
+ it 'should be possible to get the right type' do
48
+ type = ast.check_type(TypedRb::Types::TypingContext.top_level)
49
+ expect(type.to_s).to eq('Integer')
50
+ end
51
+ end
52
+
53
+
54
+ context 'with multiple variable assignment' do
55
+ let(:code) do
56
+ text =<<__CODE
57
+ a = 3
58
+ b = "blah"
59
+ a = b
60
+ a
61
+ __CODE
62
+ text
63
+ end
64
+
65
+ it 'should be possible to get the right type' do
66
+ expect {
67
+ ast.check_type(TypedRb::Types::TypingContext.top_level)
68
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
69
+ end
70
+ end
71
+
72
+ context 'in function application' do
73
+ context 'with correctly typed code' do
74
+ let(:code) do
75
+ <<__CODE
76
+ ts '#f / Integer -> String'
77
+ def f(x)
78
+ a = 'hola'
79
+ a
80
+ end
81
+
82
+ ts '#g / Integer -> String'
83
+ def g(y)
84
+ a = y
85
+ f(a)
86
+ end
87
+ __CODE
88
+ end
89
+
90
+ it 'should be possible to be passed as an argument to a function' do
91
+ expect {
92
+ ast.check_type(TypedRb::Types::TypingContext.top_level)
93
+ }.to_not raise_error
94
+ end
95
+ end
96
+
97
+ context 'with incorrectly typed code' do
98
+ let(:code) do
99
+ <<__CODE
100
+ ts '#f / String -> String'
101
+ def f(x)
102
+ x
103
+ end
104
+
105
+ ts '#g / Integer -> String'
106
+ def g(y)
107
+ a = y
108
+ f(a)
109
+ end
110
+ __CODE
111
+ end
112
+
113
+ it 'should be possible to check the error' do
114
+ expect {
115
+ ast.check_type(TypedRb::Types::TypingContext.top_level)
116
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
117
+ end
118
+ end
119
+
120
+ context 'with variable assignment using casting' do
121
+ let(:code) do
122
+ <<__CODE
123
+ a = cast(1,Numeric)
124
+ a = 2.5
125
+ __CODE
126
+ end
127
+
128
+ it 'should be possible to be passed as an argument to a function using casting' do
129
+ result = ast.check_type(TypedRb::Types::TypingContext.top_level)
130
+ expect(result.ruby_type).to eq(Numeric)
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,164 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmMlhs do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ it 'type checks array args, positive case' do
7
+ code = <<__CODE
8
+ ts '#mlhsaddition / Integer -> Integer -> Integer'
9
+ def mlhsaddition(a,b); a + b; end
10
+
11
+ ts '#mlhstest1 / Array[Integer] -> Integer'
12
+ def mlhstest1((a,b))
13
+ mlhsaddition(a,b)
14
+ end
15
+
16
+ mlhstest1([1,2])
17
+ __CODE
18
+
19
+ result = language.check(code)
20
+ expect(result.ruby_type).to eq(Integer)
21
+ end
22
+
23
+ it 'type checks array args, negative case' do
24
+ code = <<__CODE
25
+ ts '#mlhsaddition2 / String -> Integer'
26
+ def mlhsaddition2(a); 0; end
27
+
28
+ ts '#mlhstest2 / Array[Integer] -> Integer'
29
+ def mlhstest2((a,b))
30
+ mlhsaddition2(a)
31
+ end
32
+
33
+ mlhstest2([1,2])
34
+ __CODE
35
+
36
+ expect {
37
+ language.check(code)
38
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
39
+ end
40
+
41
+ it 'type checks array Pair arg, positive case' do
42
+ code = <<__CODE
43
+ ts '#mlhstestpair1 / Pair[String][Integer] -> Integer'
44
+ def mlhstestpair1((a,b)); b; end
45
+ __CODE
46
+
47
+ expect {
48
+ language.check(code)
49
+ }.to_not raise_error
50
+ end
51
+
52
+ it 'type checks array Pair arg, negative case' do
53
+ code = <<__CODE
54
+ ts '#mlhstestpair1 / Pair[String][Integer] -> Integer'
55
+ def mlhstestpair1((a,b,c)); a; end
56
+ __CODE
57
+
58
+ expect {
59
+ language.check(code)
60
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
61
+ end
62
+
63
+ it 'raises an error if the type of the argument is not an array or tuple' do
64
+ code = <<__CODE
65
+ ts '#mlhstest_error / Integer -> Integer'
66
+ def mlhstest_error((a,b))
67
+ a + b
68
+ end
69
+ __CODE
70
+
71
+ expect {
72
+ language.check(code)
73
+ }.to raise_error(TypedRb::TypeCheckError)
74
+ end
75
+
76
+ it 'type checks array args for blocks, positive case' do
77
+ code = <<__CODE
78
+ ts '#mlhsaddition3 / Integer -> Integer -> Integer'
79
+ def mlhsaddition3(a,b); a + b; end
80
+
81
+ ts '#mlhstest3 / Array[Integer] -> &(Array[Integer] -> Integer) -> Integer'
82
+ def mlhstest3(a)
83
+ yield a
84
+ end
85
+
86
+ mlhstest3([1,2]) { |(a,b)| mlhsaddition3(a,b) }
87
+ __CODE
88
+
89
+ result = language.check(code)
90
+ expect(result.ruby_type).to eq(Integer)
91
+ end
92
+
93
+ it 'type checks array args for blocks, negative case' do
94
+ code = <<__CODE
95
+ ts '#mlhsaddition4 / Integer -> Integer -> Integer'
96
+ def mlhsaddition4(a,b); a + b; end
97
+
98
+ ts '#mlhstest4 / Array[String] -> &(Array[String] -> String) -> Integer'
99
+ def mlhstest4(a)
100
+ yield a
101
+ end
102
+
103
+ mlhstest4(['a','b']) { |(a,b)| mlhsaddition4(a,b) }
104
+ __CODE
105
+
106
+ expect {
107
+ language.check(code)
108
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
109
+ end
110
+
111
+ it 'type checks pair args for blocks, positive case' do
112
+ code = <<__CODE
113
+ ts '#mlhstestpair3 / Pair[String][Integer] -> &(Pair[String][Integer] -> Integer) -> Integer'
114
+ def mlhstestpair3(p)
115
+ yield p
116
+ end
117
+
118
+ mlhstestpair3(cast(['a',1],'Pair[String][Integer]')) { |(a,b)| b }
119
+ __CODE
120
+
121
+ result = language.check(code)
122
+ expect(result.ruby_type).to eq(Integer)
123
+ end
124
+
125
+ it 'type checks pair args for blocks, negative case' do
126
+ code = <<__CODE
127
+ ts '#mlhstestpair3 / Pair[String][Integer] -> &(Pair[String][Integer] -> Integer) -> Integer'
128
+ def mlhstestpair3(p)
129
+ yield p
130
+ end
131
+
132
+ mlhstestpair3(cast(['a',1],'Pair[String][Integer]')) { |(a,b)| a }
133
+ __CODE
134
+ expect {
135
+ language.check(code)
136
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
137
+ end
138
+
139
+ it 'type checks assignation of pairs, positive case' do
140
+ code = <<__CODE
141
+ ts '#x / Pair[String][Integer] -> String'
142
+ def x(p)
143
+ a,b = p
144
+ a
145
+ end
146
+ __CODE
147
+ expect {
148
+ language.check(code)
149
+ }.to_not raise_error
150
+ end
151
+
152
+ it 'type checks assignation of pairs, negative case' do
153
+ code = <<__CODE
154
+ ts '#x / Pair[String][Integer] -> String'
155
+ def x(p)
156
+ a,b = p
157
+ b
158
+ end
159
+ __CODE
160
+ expect {
161
+ language.check(code)
162
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
163
+ end
164
+ end
@@ -0,0 +1,89 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmModule do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ it 'includes a module in a class' do
7
+ code = <<__CODE
8
+ module TMod2
9
+ ts '#x / -> String'
10
+ def x; 'test'; end
11
+ end
12
+
13
+ include TMod2
14
+ __CODE
15
+
16
+ expect do
17
+ language.check(code)
18
+ end.to_not raise_error
19
+ end
20
+
21
+ it 'detects errors in the mixed in type' do
22
+ code = <<__CODE
23
+ module TMod3
24
+ ts '#x / -> String'
25
+ def x
26
+ return_string
27
+ end
28
+ end
29
+
30
+ class TMod3C1
31
+ include TMod3
32
+ ts '#return_string / -> Integer'
33
+ def return_string; 2; end
34
+ end
35
+ __CODE
36
+
37
+ expect {
38
+ language.check(code)
39
+ }.to raise_error(TypedRb::Types::UncomparableTypes,
40
+ 'Cannot compare types Integer <=> String')
41
+ end
42
+
43
+ it 'includes a module referencing instance variables in a class' do
44
+ code = <<__CODE
45
+ module TMod4
46
+ ts '#x / Integer -> unit'
47
+ def x(i); @a = i; end
48
+ end
49
+
50
+ class TMod4C1
51
+ include TMod4
52
+
53
+ ts '#a / -> Integer'
54
+ def a; @a; end
55
+ end
56
+
57
+ TMod4C1.new.a
58
+ __CODE
59
+
60
+ result = language.check(code)
61
+ expect(result.ruby_type).to eq(Integer)
62
+ end
63
+
64
+ it 'typechecks the inclusion of a module in multiple classes' do
65
+ code = <<__CODE
66
+ module TMod4
67
+ ts '#x / Integer -> unit'
68
+ def x(i); @a = i; end
69
+ end
70
+
71
+ class TMod4C1
72
+ include TMod4
73
+
74
+ ts '#a / -> Integer'
75
+ def a; @a; end
76
+ end
77
+
78
+ class TMod4C2
79
+ include TMod4
80
+ end
81
+
82
+ TMod4C2.new.x(3)
83
+ TMod4C1.new.a
84
+ __CODE
85
+
86
+ result = language.check(code)
87
+ expect(result.ruby_type).to eq(Integer)
88
+ end
89
+ end
@@ -0,0 +1,31 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmError do
4
+
5
+ let(:language) { TypedRb::Language.new }
6
+
7
+ context 'with raise, one error' do
8
+ it 'type-checks it correctly' do
9
+ code = <<__END
10
+ 1 || raise(StandardError)
11
+ __END
12
+ result = language.check(code)
13
+ expect(result.to_s).to eq('Integer')
14
+ end
15
+ end
16
+
17
+ context 'with raise, only errors' do
18
+ it 'type-checks it correctly' do
19
+ code = <<__END
20
+ ts '#x / -> Integer'
21
+ def x
22
+ raise(StandardError) || raise(StandardError)
23
+ end
24
+ __END
25
+ expect {
26
+ language.check(code)
27
+ }.not_to raise_error(TypedRb::Types::UncomparableTypes)
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,25 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmRangeLiteral do
4
+
5
+ let(:language) { TypedRb::Language.new }
6
+
7
+ it 'parses ranges with the same type' do
8
+ code = '0..10'
9
+ result = language.check(code)
10
+ expect(result.ruby_type).to eq(Range)
11
+ expect(result.type_vars.first.bound.ruby_type).to eq(Integer)
12
+
13
+ code = '"a"..."z"'
14
+ result = language.check(code)
15
+ expect(result.ruby_type).to eq(Range)
16
+ expect(result.type_vars.first.bound.ruby_type).to eq(String)
17
+ end
18
+
19
+ it 'fails for incompatible types' do
20
+ code = '0..10.0'
21
+ expect {
22
+ language.check(code)
23
+ }.to raise_error
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmRegexp do
4
+
5
+ let(:language) { TypedRb::Language.new }
6
+
7
+ context 'with a regular expression' do
8
+
9
+ it 'parsed the Regexp type correctly' do
10
+ result = language.check('/test/')
11
+ expect(result).to eq(tyregexp)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,45 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmReturn do
4
+
5
+ describe 'Simple for loop' do
6
+ let(:language) { TypedRb::Language.new }
7
+
8
+ it 'type checks a for statement, positive case' do
9
+ code = <<__CODE
10
+ ts '#test_i_fn / Integer -> Integer'
11
+ def test_i_fn(x); return 1; end
12
+
13
+ test_i_fn(1)
14
+ __CODE
15
+
16
+ parsed = language.check(code)
17
+ expect(parsed.ruby_type).to eq(Integer)
18
+ end
19
+
20
+ it 'type checks a for statement, no return value' do
21
+ code = <<__CODE
22
+ ts '#test_i_fn / Integer -> Integer'
23
+ def test_i_fn(x); return; end
24
+
25
+ test_i_fn(1)
26
+ __CODE
27
+
28
+ parsed = language.check(code)
29
+ expect(parsed.ruby_type).to eq(Integer)
30
+ end
31
+
32
+ it 'type checks a for statement, negative case' do
33
+ code = <<__CODE
34
+ ts '#test_i_fn / Integer -> Integer'
35
+ def test_i_fn(x); return '1'; end
36
+
37
+ test_i_fn(1)
38
+ __CODE
39
+
40
+ expect {
41
+ language.check(code)
42
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,26 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmSend do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ it 'casts any value to the provided type' do
7
+ expr = 'cast(\'string\', Integer)'
8
+
9
+ result = language.check(expr)
10
+ expect(result).to eq(tyinteger)
11
+ end
12
+
13
+ it 'casts values when provided as strings' do
14
+ expr = 'cast(\'string\', \'Integer\')'
15
+
16
+ result = language.check(expr)
17
+ expect(result).to eq(tyinteger)
18
+ end
19
+
20
+ it 'casts values when provided as a generic type' do
21
+ expr = 'cast(\'string\', \'Array[Integer]\')'
22
+
23
+ result = language.check(expr)
24
+ expect(result.to_s).to eq('Array[Integer]')
25
+ end
26
+ end
@@ -0,0 +1,42 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmSend do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ context 'with class methods' do
7
+ it 'is possible to send messages to the class objects' do
8
+ expr = <<__END
9
+ class Integer
10
+ ts '#+ / Integer -> Integer'
11
+ end
12
+
13
+ class TypeCM1
14
+
15
+ ts '.a / -> Integer'
16
+ def self.a
17
+ 1
18
+ end
19
+
20
+ class << self
21
+ ts '.b / -> Integer'
22
+ def b
23
+ 2
24
+ end
25
+ end
26
+
27
+ class << TypeCM1
28
+ ts '.c / -> Integer'
29
+ def c
30
+ 3
31
+ end
32
+ end
33
+ end
34
+
35
+ TypeCM1.a + TypeCM1.c + TypeCM1.c
36
+ __END
37
+
38
+ result = language.check(expr)
39
+ expect(result.ruby_type).to eq(Integer)
40
+ end
41
+ end
42
+ end