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