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,66 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmAbs do
4
+
5
+ it 'parses a lambda function with multiple args' do
6
+ parsed = parse('->(x,y) { x + y }')
7
+
8
+ expect(parsed).to be_instance_of(described_class)
9
+ expect(parsed.arity).to eq(2)
10
+ expect(parsed.abs_type).to eq(:lambda)
11
+
12
+ result = parsed.check_type(top_level_typing_context)
13
+
14
+ expect(result.from[0]).to be_instance_of(TypedRb::Types::Polymorphism::TypeVariable)
15
+ expect(result.from[1]).to be_instance_of(TypedRb::Types::Polymorphism::TypeVariable)
16
+ expect(result.from.size).to eq(2)
17
+ expect(result.from[0].variable.index("lambda:#{parsed.term.receiver.val}")).to_not be_nil
18
+ expect(result.from[1].variable.index("lambda:#{parsed.term.args[0].val}")).to_not be_nil
19
+ end
20
+
21
+ it 'check types creating the right constraints for the type variables' do
22
+ parsed = parse('->(x,y) { x + y }')
23
+ expect(parsed.arity).to eq(2)
24
+ expect(parsed.abs_type).to eq(:lambda)
25
+
26
+ result = parsed.check_type(top_level_typing_context)
27
+
28
+ TypedRb::Types::TypingContext.with_context(result.local_typing_context) do
29
+ expect(result.from.size).to eq(2)
30
+ expect(result.from[0]).to be_a(TypedRb::Types::Polymorphism::TypeVariable)
31
+ expect(result.from[0].constraints[0][1]).to eq(:send)
32
+ expect(result.from[1]).to be_a(TypedRb::Types::Polymorphism::TypeVariable)
33
+ expect(result.to).to be_a(TypedRb::Types::Polymorphism::TypeVariable)
34
+ end
35
+ end
36
+
37
+ it 'parses a Proc with multiple args' do
38
+ parsed = parse('Proc.new{ |x,y| x + y }')
39
+
40
+ expect(parsed).to be_instance_of(described_class)
41
+ expect(parsed.arity).to eq(2)
42
+ expect(parsed.abs_type).to eq(:proc)
43
+
44
+ result = parsed.check_type(top_level_typing_context)
45
+
46
+ expect(result.from[0]).to be_instance_of(TypedRb::Types::Polymorphism::TypeVariable)
47
+ expect(result.from[1]).to be_instance_of(TypedRb::Types::Polymorphism::TypeVariable)
48
+ expect(result.from.size).to eq(2)
49
+ expect(result.from[0].variable.index("lambda:#{parsed.term.receiver.val}")).to_not be_nil
50
+ expect(result.from[1].variable.index("lambda:#{parsed.term.args[0].val}")).to_not be_nil
51
+ end
52
+
53
+ it 'check types creating the right constraints for the type variables' do
54
+ parsed = parse('Proc.new { |x,y| x + y }')
55
+ expect(parsed.arity).to eq(2)
56
+ expect(parsed.abs_type).to eq(:proc)
57
+ result = parsed.check_type(top_level_typing_context)
58
+ TypedRb::Types::TypingContext.with_context(result.local_typing_context) do
59
+ expect(result.from.size).to eq(2)
60
+ expect(result.from[0]).to be_a(TypedRb::Types::Polymorphism::TypeVariable)
61
+ expect(result.from[0].constraints[0][1]).to eq(:send)
62
+ expect(result.from[1]).to be_a(TypedRb::Types::Polymorphism::TypeVariable)
63
+ expect(result.to).to be_a(TypedRb::Types::Polymorphism::TypeVariable)
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,36 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmArrayLiteral do
4
+
5
+ it 'parses array literals with the same type' do
6
+ code = '[1, 2, 3]'
7
+
8
+ parsed = TypedRb::Language.new.check(code)
9
+ expect(parsed.ruby_type).to eq(Array)
10
+ expect(parsed.type_vars.first.bound.ruby_type).to eq(Integer)
11
+ end
12
+
13
+ it 'parses array literals with compatible types' do
14
+ code = '[1, Numeric.new, 3]'
15
+
16
+ parsed = TypedRb::Language.new.check(code)
17
+ expect(parsed.ruby_type).to eq(Array)
18
+ expect(parsed.type_vars.first.bound.ruby_type).to eq(Numeric)
19
+ end
20
+
21
+ it 'parses array literals with nil values' do
22
+ code = '[1, Numeric.new, nil]'
23
+
24
+ parsed = TypedRb::Language.new.check(code)
25
+ expect(parsed.ruby_type).to eq(Array)
26
+ expect(parsed.type_vars.first.bound.ruby_type).to eq(Numeric)
27
+ end
28
+
29
+ it 'parses array literals with incompatible values' do
30
+ code = '[1, "string"]'
31
+
32
+ parsed = TypedRb::Language.new.check(code)
33
+ expect(parsed.ruby_type).to eq(Array)
34
+ expect(parsed.type_vars.first.bound.ruby_type).to eq(Object)
35
+ end
36
+ end
@@ -0,0 +1,39 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmCaseWhen do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ it 'type checks a simple case/when statement' do
7
+ code = <<__CODE
8
+ a = 'a'
9
+ case a
10
+ when 'a'
11
+ a
12
+ when 'b'
13
+ a
14
+ else
15
+ 'other'
16
+ end
17
+ __CODE
18
+
19
+ parsed = language.check(code)
20
+ expect(parsed.ruby_type).to eq(String)
21
+ end
22
+
23
+ it 'Promotes types to union type in case/when expressions' do
24
+ code = <<__CODE
25
+ a = 'a'
26
+ case a
27
+ when 'a'
28
+ a
29
+ when 'b'
30
+ 0
31
+ else
32
+ 'other'
33
+ end
34
+ __CODE
35
+
36
+ parsed = language.check(code)
37
+ expect(parsed.ruby_type).to eq(Object)
38
+ end
39
+ end
@@ -0,0 +1,67 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmClass do
4
+ let(:language) { TypedRb::Language.new }
5
+
6
+ it 'parses a generic type' do
7
+ code = <<__CODE
8
+ ts 'type Pod[X<Numeric]'
9
+ class Pod
10
+
11
+ ts '#put / [X] -> unit'
12
+ def put(n)
13
+ @value = n
14
+ end
15
+
16
+ ts '#take / -> [X]'
17
+ def take
18
+ @value
19
+ end
20
+ end
21
+
22
+ Pod
23
+ __CODE
24
+
25
+ parsed = language.check(code)
26
+
27
+ expect(parsed).to be_instance_of(TypedRb::Types::TyGenericSingletonObject)
28
+ value_instance_var = parsed.local_typing_context.type_variables_register[[:instance_variable, Pod, :@value]]
29
+ expect(value_instance_var).to_not be_nil
30
+ expect(value_instance_var.variable.index('Pod:@value')).to_not be_nil
31
+ value_instance_var_constraints = parsed.local_typing_context.constraints[value_instance_var.variable]
32
+ expect(value_instance_var_constraints.size).to eq(2)
33
+ end
34
+
35
+ it 'handles nested classes' do
36
+ code = <<__CODE
37
+ module TCNS
38
+ class TC
39
+ ts '#test / -> Integer'
40
+ def test; 1; end
41
+ end
42
+ end
43
+
44
+ TCNS::TC.new.test
45
+ __CODE
46
+
47
+ result = language.check(code)
48
+ expect(result.ruby_type).to eq(Integer)
49
+ end
50
+
51
+ it 'handles nested classes in return arguments' do
52
+ code = <<__CODE
53
+ module TCNS
54
+ class TC2; end
55
+ class TC3
56
+ ts '#test / -> Class'
57
+ def test; TC2; end
58
+ end
59
+ end
60
+
61
+ TCNS::TC3.new.test
62
+ __CODE
63
+
64
+ result = language.check(code)
65
+ expect(result.ruby_type).to eq(Class)
66
+ end
67
+ end
@@ -0,0 +1,10 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmDefined do
4
+
5
+ it 'parses a defined invocation' do
6
+ parsed = parse('defined? 2')
7
+ expect(parsed).to be_instance_of(described_class)
8
+ expect(parsed.expression).to be_instance_of(TypedRb::Model::TmInt)
9
+ end
10
+ end
@@ -0,0 +1,150 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmFor 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); x + 1; end
12
+
13
+ for i in 0..3
14
+ test_i_fn(i)
15
+ end
16
+ __CODE
17
+
18
+ parsed = language.check(code)
19
+ expect(parsed.ruby_type).to eq(Integer)
20
+ end
21
+
22
+ it 'type checks a for statement, negative case' do
23
+ code = <<__CODE
24
+ ts '#test_s_fn / String -> Integer'
25
+ def test_s_fn(x); 0; end
26
+
27
+ for i in 0..3
28
+ test_s_fn(i)
29
+ end
30
+ __CODE
31
+
32
+ expect {
33
+ language.check(code)
34
+ }.to raise_error(TypedRb::Types::UncomparableTypes)
35
+ end
36
+ end
37
+
38
+ describe 'Simple for loop, break' do
39
+ let(:language) { TypedRb::Language.new }
40
+
41
+ it 'type checks a for statement' do
42
+ code = <<__CODE
43
+ ts '#test_i_fn / Integer -> Integer'
44
+ def test_i_fn(x); x + 1; end
45
+
46
+ for i in 0..3
47
+ break 7
48
+ ""
49
+ end
50
+ __CODE
51
+
52
+ parsed = language.check(code)
53
+ expect(parsed.ruby_type).to eq(Integer)
54
+ end
55
+
56
+ it 'type checks a for statement, no value' do
57
+ code = <<__CODE
58
+ ts '#test_i_fn / Integer -> Integer'
59
+ def test_i_fn(x); x + 1; end
60
+
61
+ for i in 0..3
62
+ break
63
+ ""
64
+ end
65
+ __CODE
66
+
67
+ parsed = language.check(code)
68
+ expect(parsed.ruby_type).to eq(NilClass)
69
+ end
70
+
71
+ it 'type checks a for statement returning an array' do
72
+ code = <<__CODE
73
+ for i in 0..3
74
+ break 7,3
75
+ ""
76
+ end
77
+ __CODE
78
+
79
+ parsed = language.check(code)
80
+ expect(parsed.to_s).to eq('Array[Integer]')
81
+ end
82
+ end
83
+
84
+ describe 'Simple for loop, next' do
85
+ let(:language) { TypedRb::Language.new }
86
+
87
+ it 'type checks a for statement' do
88
+ code = <<__CODE
89
+ a = for i in 0..3
90
+ next(3)
91
+ nil
92
+ end
93
+ a
94
+ __CODE
95
+
96
+ parsed = language.check(code)
97
+ expect(parsed.ruby_type).to eq(Integer)
98
+ end
99
+
100
+ it 'type checks a for statement, no value' do
101
+ code = <<__CODE
102
+ a = for i in 0..3
103
+ next
104
+ nil
105
+ end
106
+ a
107
+ __CODE
108
+
109
+ parsed = language.check(code)
110
+ expect(parsed.ruby_type).to eq(NilClass)
111
+ end
112
+ end
113
+
114
+ describe 'Simple for loop, next array' do
115
+ let(:language) { TypedRb::Language.new }
116
+
117
+ it 'type checks a for statement' do
118
+ code = <<__CODE
119
+ a = for i in 0..3
120
+ next 3,4
121
+ nil
122
+ end
123
+ a
124
+ __CODE
125
+
126
+ parsed = language.check(code)
127
+ expect(parsed.to_s).to eq('Array[Integer]')
128
+ end
129
+ end
130
+
131
+ describe 'Simple for loop, either' do
132
+ let(:language) { TypedRb::Language.new }
133
+
134
+ it 'type checks a for statement' do
135
+ code = <<__CODE
136
+ a = for i in 0..3
137
+ if i == 0
138
+ next(3)
139
+ else
140
+ i
141
+ end
142
+ end
143
+ a
144
+ __CODE
145
+
146
+ parsed = language.check(code)
147
+ expect(parsed.ruby_type).to eq(Integer)
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,11 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmFun do
4
+ it 'parses a function with rest args' do
5
+ parsed = parse('def f(a,*rest); end')
6
+ expect(parsed).to be_instance_of(described_class)
7
+ expect(parsed.args.size).to eq(2)
8
+ expect(parsed.args.last.first).to eq(:restarg)
9
+ parsed.check_type(TypedRb::Types::TypingContext.top_level)
10
+ end
11
+ end
@@ -0,0 +1,40 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmHashLiteral do
4
+
5
+ it 'parses hash literals with the same type' do
6
+ code = '{:a => 1, :b => 2}'
7
+
8
+ parsed = TypedRb::Language.new.check(code)
9
+ expect(parsed.ruby_type).to eq(Hash)
10
+ expect(parsed.type_vars.first.bound.ruby_type).to eq(Symbol)
11
+ expect(parsed.type_vars.last.bound.ruby_type).to eq(Integer)
12
+ end
13
+
14
+ it 'parses hash literals with compatible types' do
15
+ code = '{2 => 1, 3 => Numeric.new, Numeric.new => 4}'
16
+
17
+ parsed = TypedRb::Language.new.check(code)
18
+ expect(parsed.ruby_type).to eq(Hash)
19
+ expect(parsed.type_vars.first.bound.ruby_type).to eq(Numeric)
20
+ expect(parsed.type_vars.last.bound.ruby_type).to eq(Numeric)
21
+ end
22
+
23
+ it 'parses array literals with nil values' do
24
+ code = '{:x => 1, nil => Numeric.new, :z => nil}'
25
+
26
+ parsed = TypedRb::Language.new.check(code)
27
+ expect(parsed.ruby_type).to eq(Hash)
28
+ expect(parsed.type_vars.first.bound.ruby_type).to eq(Symbol)
29
+ expect(parsed.type_vars.last.bound.ruby_type).to eq(Numeric)
30
+ end
31
+
32
+ it 'parses array literals with incompatible values' do
33
+ code = '{:x => 1, 2 => "string"}'
34
+
35
+ parsed = TypedRb::Language.new.check(code)
36
+ expect(parsed.ruby_type).to eq(Hash)
37
+ expect(parsed.type_vars.first.bound.ruby_type).to eq(Object)
38
+ expect(parsed.type_vars.last.bound.ruby_type).to eq(Object)
39
+ end
40
+ end
@@ -0,0 +1,104 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmMassAsgn do
4
+
5
+ it 'parses mass assignment' do
6
+ code = <<__CODE
7
+ ts '#fma1 / -> Array[Integer]'
8
+ def fma1; Array.(Integer).new; end
9
+
10
+ a,b = fma1
11
+ __CODE
12
+
13
+ parsed = TypedRb::Language.new.check(code)
14
+ expect(parsed.ruby_type).to eq(Array)
15
+
16
+ code = <<__CODE
17
+ ts '#fma1 / -> Array[Integer]'
18
+ def fma1; Array.(Integer).new; end
19
+
20
+ a,b = fma1
21
+ a
22
+ __CODE
23
+
24
+ parsed = TypedRb::Language.new.check(code)
25
+ expect(parsed.bound.ruby_type).to eq(Integer)
26
+
27
+
28
+ code = <<__CODE
29
+ ts '#fma1 / -> Array[Integer]'
30
+ def fma1; Array.(Integer).new; end
31
+
32
+ a,b = fma1
33
+ b
34
+ __CODE
35
+
36
+ parsed = TypedRb::Language.new.check(code)
37
+ expect(parsed.bound.ruby_type).to eq(Integer)
38
+
39
+ code = <<__CODE
40
+ ts '#fma1 / -> Array[Integer]'
41
+ def fma1; Array.(Integer).new; end
42
+
43
+ ts '#fmai1 / -> Integer'
44
+ def fmai1
45
+ a,b = fma1
46
+ a
47
+ end
48
+
49
+ fmai1
50
+ __CODE
51
+ parsed = TypedRb::Language.new.check(code)
52
+ expect(parsed.ruby_type).to eq(Integer)
53
+ end
54
+
55
+ it 'parses mass assignment when returning scalar types' do
56
+ code = <<__CODE
57
+ ts '#fma2 / -> String'
58
+ def fma2; 'string'; end
59
+
60
+ a,b = fma2
61
+ __CODE
62
+
63
+ parsed = TypedRb::Language.new.check(code)
64
+ expect(parsed.ruby_type).to eq(String)
65
+
66
+ code = <<__CODE
67
+ ts '#fma2 / -> String'
68
+ def fma2; 'string'; end
69
+
70
+ a,b = fma2
71
+ a
72
+ __CODE
73
+
74
+ parsed = TypedRb::Language.new.check(code)
75
+ expect(parsed.ruby_type).to eq(String)
76
+
77
+
78
+ code = <<__CODE
79
+ ts '#fma2 / -> String'
80
+ def fma2; 'string'; end
81
+
82
+ a,b = fma2
83
+ b
84
+ __CODE
85
+
86
+ parsed = TypedRb::Language.new.check(code)
87
+ expect(parsed).to eq(tyunit)
88
+
89
+ code = <<__CODE
90
+ ts '#fma2 / -> String'
91
+ def fma2; 'string'; end
92
+
93
+ ts '#fmai2 / -> String'
94
+ def fmai2
95
+ a,b = fma2
96
+ a
97
+ end
98
+
99
+ fmai2
100
+ __CODE
101
+ parsed = TypedRb::Language.new.check(code)
102
+ expect(parsed.ruby_type).to eq(String)
103
+ end
104
+ end
@@ -0,0 +1,42 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmModule do
4
+
5
+ it 'parses ruby modules' do
6
+ code = <<__CODE
7
+ module TMod1
8
+ ts '#x / -> unit'
9
+ def x; 'test'; end
10
+ end
11
+ __CODE
12
+
13
+ parsed = TypedRb::Language.new.check(code)
14
+ expect(parsed.is_a?(TypedRb::Types::TyExistentialType)).to eq(true)
15
+ expect(parsed.ruby_type).to eq(TMod1)
16
+ end
17
+
18
+ it 'parses nested modules' do
19
+ code = <<__CODE
20
+ module TMod1
21
+ module TMod2
22
+ module TMod3
23
+ module TMod4
24
+ class TMod4C1
25
+ ts '#x / -> Integer'
26
+ def x
27
+ 0
28
+ end
29
+ end
30
+ end
31
+ end
32
+ class TMod4C2; end
33
+ end
34
+ end
35
+
36
+ TMod1::TMod2::TMod3::TMod4::TMod4C1.new.x
37
+ __CODE
38
+
39
+ parsed = TypedRb::Language.new.check(code)
40
+ expect(parsed.ruby_type).to eq(Integer)
41
+ end
42
+ end
@@ -0,0 +1,9 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmRegexp do
4
+
5
+ it 'parses a regular expression' do
6
+ parsed = parse('/[Rr]eg[Ee]xp/')
7
+ expect(parsed).to be_instance_of(described_class)
8
+ end
9
+ end
@@ -0,0 +1,47 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmArrayLiteral do
4
+ it 'parses return instructions with single types' do
5
+ code = <<__CODE
6
+ ts '#fret1 / -> Integer'
7
+ def fret1
8
+ return 1
9
+ end
10
+
11
+ fret1
12
+ __CODE
13
+
14
+ parsed = TypedRb::Language.new.check(code)
15
+ expect(parsed.ruby_type).to eq(Integer)
16
+ end
17
+
18
+ it 'parses return instructions with multiple compatible types' do
19
+ code = <<__CODE
20
+ ts '#fret2 / -> Array[Integer]'
21
+ def fret2
22
+ return 1, 2
23
+ end
24
+
25
+ fret2
26
+ __CODE
27
+
28
+ parsed = TypedRb::Language.new.check(code)
29
+ expect(parsed.ruby_type).to eq(Array)
30
+ expect(parsed.type_vars.first.bound.ruby_type).to eq(Integer)
31
+ end
32
+
33
+ it 'parses return instructions with multiple incompatible types' do
34
+ code = <<__CODE
35
+ ts '#fret3 / -> Array[Object]'
36
+ def fret3
37
+ return 1, 'string'
38
+ end
39
+
40
+ fret3
41
+ __CODE
42
+
43
+ parsed = TypedRb::Language.new.check(code)
44
+ expect(parsed.ruby_type).to eq(Array)
45
+ expect(parsed.type_vars.first.bound.ruby_type).to eq(Object)
46
+ end
47
+ end
@@ -0,0 +1,27 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmSClass do
4
+
5
+ it 'parses a singleton class' do
6
+ code = <<__CODE
7
+ ts 'type Pod1[X<Numeric]'
8
+ class Pod1
9
+
10
+ ts '.put / [X] -> unit'
11
+ def self.put(n)
12
+ @value = n
13
+ end
14
+
15
+ class << self
16
+ ts '.take / -> [X]'
17
+ def take
18
+ @value
19
+ end
20
+ end
21
+ end
22
+ __CODE
23
+
24
+ TypedRb::Language.new.check(code)
25
+ expect(BasicObject::TypeRegistry.send(:registry)[[:class,Pod1]].keys).to eq(['put', 'take'])
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmSelf do
4
+ it 'returns the self reference type' do
5
+ code = <<__CODE
6
+ class TSelfRef1
7
+ ts '#test / -> TSelfRef1'
8
+ def test
9
+ self
10
+ end
11
+ end
12
+
13
+ TSelfRef1.new.test
14
+ __CODE
15
+
16
+ parsed = TypedRb::Language.new.check(code)
17
+ expect(parsed.ruby_type).to eq(TSelfRef1)
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmStringInterpolation do
4
+
5
+ it 'parses interpolation of strings' do
6
+ parsed = parse('"this #{is} an #{interpolation}"')
7
+ expect(parsed).to be_instance_of(described_class)
8
+ expect(parsed.units.size).to eq(4)
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe TypedRb::Model::TmSymbolInterpolation do
4
+
5
+ it 'parses interpolation of strings' do
6
+ parsed = parse(':"this #{is} an #{interpolation}"')
7
+ expect(parsed).to be_instance_of(described_class)
8
+ expect(parsed.units.size).to eq(4)
9
+ end
10
+ end