steep 0.1.0.pre2 → 0.1.0

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 (119) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +1 -1
  3. data/README.md +146 -33
  4. data/bin/smoke_runner.rb +43 -10
  5. data/lib/steep/ast/annotation/collection.rb +93 -0
  6. data/lib/steep/ast/annotation.rb +131 -0
  7. data/lib/steep/ast/buffer.rb +47 -0
  8. data/lib/steep/ast/location.rb +82 -0
  9. data/lib/steep/ast/method_type.rb +116 -0
  10. data/lib/steep/ast/signature/class.rb +33 -0
  11. data/lib/steep/ast/signature/const.rb +17 -0
  12. data/lib/steep/ast/signature/env.rb +123 -0
  13. data/lib/steep/ast/signature/extension.rb +21 -0
  14. data/lib/steep/ast/signature/gvar.rb +17 -0
  15. data/lib/steep/ast/signature/interface.rb +31 -0
  16. data/lib/steep/ast/signature/members.rb +71 -0
  17. data/lib/steep/ast/signature/module.rb +21 -0
  18. data/lib/steep/ast/type_params.rb +13 -0
  19. data/lib/steep/ast/types/any.rb +39 -0
  20. data/lib/steep/ast/types/bot.rb +39 -0
  21. data/lib/steep/ast/types/class.rb +35 -0
  22. data/lib/steep/ast/types/helper.rb +21 -0
  23. data/lib/steep/ast/types/instance.rb +39 -0
  24. data/lib/steep/ast/types/intersection.rb +74 -0
  25. data/lib/steep/ast/types/name.rb +124 -0
  26. data/lib/steep/ast/types/self.rb +39 -0
  27. data/lib/steep/ast/types/top.rb +39 -0
  28. data/lib/steep/ast/types/union.rb +74 -0
  29. data/lib/steep/ast/types/var.rb +57 -0
  30. data/lib/steep/ast/types/void.rb +35 -0
  31. data/lib/steep/cli.rb +28 -1
  32. data/lib/steep/drivers/annotations.rb +32 -0
  33. data/lib/steep/drivers/check.rb +53 -77
  34. data/lib/steep/drivers/scaffold.rb +303 -0
  35. data/lib/steep/drivers/utils/each_signature.rb +66 -0
  36. data/lib/steep/drivers/utils/validator.rb +115 -0
  37. data/lib/steep/drivers/validate.rb +39 -0
  38. data/lib/steep/errors.rb +291 -19
  39. data/lib/steep/interface/abstract.rb +44 -0
  40. data/lib/steep/interface/builder.rb +470 -0
  41. data/lib/steep/interface/instantiated.rb +126 -0
  42. data/lib/steep/interface/ivar_chain.rb +26 -0
  43. data/lib/steep/interface/method.rb +60 -0
  44. data/lib/steep/{interface.rb → interface/method_type.rb} +111 -100
  45. data/lib/steep/interface/substitution.rb +65 -0
  46. data/lib/steep/module_name.rb +116 -0
  47. data/lib/steep/parser.rb +1314 -814
  48. data/lib/steep/parser.y +536 -175
  49. data/lib/steep/source.rb +220 -25
  50. data/lib/steep/subtyping/check.rb +673 -0
  51. data/lib/steep/subtyping/constraints.rb +275 -0
  52. data/lib/steep/subtyping/relation.rb +41 -0
  53. data/lib/steep/subtyping/result.rb +126 -0
  54. data/lib/steep/subtyping/trace.rb +48 -0
  55. data/lib/steep/subtyping/variable_occurrence.rb +49 -0
  56. data/lib/steep/subtyping/variable_variance.rb +69 -0
  57. data/lib/steep/type_construction.rb +1630 -524
  58. data/lib/steep/type_inference/block_params.rb +100 -0
  59. data/lib/steep/type_inference/constant_env.rb +55 -0
  60. data/lib/steep/type_inference/send_args.rb +222 -0
  61. data/lib/steep/type_inference/type_env.rb +226 -0
  62. data/lib/steep/type_name.rb +27 -7
  63. data/lib/steep/typing.rb +4 -0
  64. data/lib/steep/version.rb +1 -1
  65. data/lib/steep.rb +71 -16
  66. data/smoke/and/a.rb +4 -2
  67. data/smoke/array/a.rb +4 -5
  68. data/smoke/array/b.rb +4 -4
  69. data/smoke/block/a.rb +2 -2
  70. data/smoke/block/a.rbi +2 -0
  71. data/smoke/block/b.rb +15 -0
  72. data/smoke/case/a.rb +3 -3
  73. data/smoke/class/a.rb +3 -3
  74. data/smoke/class/b.rb +0 -2
  75. data/smoke/class/d.rb +2 -2
  76. data/smoke/class/e.rb +1 -1
  77. data/smoke/class/f.rb +2 -2
  78. data/smoke/class/g.rb +8 -0
  79. data/smoke/const/a.rb +3 -3
  80. data/smoke/dstr/a.rb +1 -1
  81. data/smoke/ensure/a.rb +22 -0
  82. data/smoke/enumerator/a.rb +6 -6
  83. data/smoke/enumerator/b.rb +22 -0
  84. data/smoke/extension/a.rb +2 -2
  85. data/smoke/extension/b.rb +3 -3
  86. data/smoke/extension/c.rb +1 -1
  87. data/smoke/hello/hello.rb +2 -2
  88. data/smoke/if/a.rb +4 -2
  89. data/smoke/kwbegin/a.rb +8 -0
  90. data/smoke/literal/a.rb +5 -5
  91. data/smoke/method/a.rb +5 -5
  92. data/smoke/method/a.rbi +4 -0
  93. data/smoke/method/b.rb +29 -0
  94. data/smoke/module/a.rb +3 -3
  95. data/smoke/module/a.rbi +9 -0
  96. data/smoke/module/b.rb +2 -2
  97. data/smoke/module/c.rb +1 -1
  98. data/smoke/module/d.rb +5 -0
  99. data/smoke/module/e.rb +13 -0
  100. data/smoke/module/f.rb +13 -0
  101. data/smoke/rescue/a.rb +62 -0
  102. data/smoke/super/a.rb +2 -2
  103. data/smoke/type_case/a.rb +35 -0
  104. data/smoke/yield/a.rb +2 -2
  105. data/stdlib/builtin.rbi +463 -24
  106. data/steep.gemspec +3 -2
  107. metadata +91 -29
  108. data/lib/steep/annotation.rb +0 -223
  109. data/lib/steep/signature/class.rb +0 -450
  110. data/lib/steep/signature/extension.rb +0 -51
  111. data/lib/steep/signature/interface.rb +0 -49
  112. data/lib/steep/types/any.rb +0 -31
  113. data/lib/steep/types/class.rb +0 -27
  114. data/lib/steep/types/instance.rb +0 -27
  115. data/lib/steep/types/merge.rb +0 -32
  116. data/lib/steep/types/name.rb +0 -57
  117. data/lib/steep/types/union.rb +0 -42
  118. data/lib/steep/types/var.rb +0 -38
  119. data/lib/steep/types.rb +0 -4
@@ -0,0 +1,100 @@
1
+ module Steep
2
+ module TypeInference
3
+ class BlockParams
4
+ class Param
5
+ attr_reader :var
6
+ attr_reader :type
7
+ attr_reader :value
8
+ attr_reader :node
9
+
10
+ def initialize(var:, type:, value:, node:)
11
+ @var = var
12
+ @type = type
13
+ @value = value
14
+ @node = node
15
+ end
16
+
17
+ def ==(other)
18
+ other.is_a?(Param) && other.var == var && other.type == type && other.value == value && other.node == node
19
+ end
20
+
21
+ alias eql? ==
22
+
23
+ def hash
24
+ self.class.hash ^ var.hash ^ type.hash ^ value.hash ^ node.hash
25
+ end
26
+ end
27
+
28
+ attr_reader :params
29
+ attr_reader :rest
30
+
31
+ def initialize(params:, rest:)
32
+ @params = params
33
+ @rest = rest
34
+ end
35
+
36
+ def self.from_node(node, annotations:)
37
+ params = []
38
+ rest = nil
39
+
40
+ node.children.each do |arg|
41
+ var = arg.children.first
42
+ type = annotations.lookup_var_type(var.name)
43
+
44
+ case arg.type
45
+ when :arg, :procarg0
46
+ params << Param.new(var: var, type: type, value: nil, node: arg)
47
+ when :optarg
48
+ params << Param.new(var: var, type: type, value: arg.children.last, node: arg)
49
+ when :restarg
50
+ rest = Param.new(var: var, type: type, value: nil, node: arg)
51
+ end
52
+ end
53
+
54
+ new(
55
+ params: params,
56
+ rest: rest
57
+ )
58
+ end
59
+
60
+ def zip(params_type)
61
+ [].tap do |zip|
62
+ types = params_type.flat_unnamed_params
63
+ params.each do |param|
64
+ type = types.shift&.last || params_type.rest || AST::Types::Any.new
65
+
66
+ if type
67
+ zip << [param, type]
68
+ end
69
+ end
70
+
71
+ if rest
72
+ if types.empty?
73
+ array = AST::Types::Name.new_instance(
74
+ name: :Array,
75
+ args: [params_type.rest || AST::Types::Any.new]
76
+ )
77
+ zip << [rest, array]
78
+ else
79
+ union = AST::Types::Union.build(types: types.map(&:last) + [params_type.rest])
80
+ array = AST::Types::Name.new_instance(
81
+ name: :Array,
82
+ args: [union]
83
+ )
84
+ zip << [rest, array]
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ def each(&block)
91
+ if block_given?
92
+ params.each &block
93
+ yield rest if rest
94
+ else
95
+ enum_for :each
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,55 @@
1
+ module Steep
2
+ module TypeInference
3
+ class ConstantEnv
4
+ attr_reader :builder
5
+ attr_reader :current_namespace
6
+ attr_reader :cache
7
+
8
+ def initialize(builder:, current_namespace:)
9
+ @cache = {}
10
+ @builder = builder
11
+ @current_namespace = current_namespace
12
+ end
13
+
14
+ def signatures
15
+ builder.signatures
16
+ end
17
+
18
+ def lookup(name)
19
+ unless cache.key?(name)
20
+ cache[name] = lookup0(name, namespace: current_namespace)
21
+ end
22
+
23
+ cache[name]
24
+ end
25
+
26
+ def lookup0(name, namespace:)
27
+ if name.absolute?
28
+ case
29
+ when signatures.module_name?(name)
30
+ AST::Types::Name.new_module(name: name)
31
+ when signatures.class_name?(name)
32
+ AST::Types::Name.new_class(name: name, constructor: true)
33
+ when signatures.const_name?(name)
34
+ builder.absolute_type(signatures.find_const(name).type, current: nil)
35
+ end
36
+ else
37
+ if namespace
38
+ case
39
+ when signatures.module_name?(name, current_module: namespace)
40
+ AST::Types::Name.new_module(name: namespace + name)
41
+ when signatures.class_name?(name, current_module: namespace)
42
+ AST::Types::Name.new_class(name: namespace + name, constructor: true)
43
+ when signatures.const_name?(name, current_module: namespace)
44
+ builder.absolute_type(signatures.find_const(name, current_module: namespace).type, current: nil)
45
+ else
46
+ lookup0(name, namespace: namespace.parent)
47
+ end
48
+ else
49
+ lookup0(name.absolute!, namespace: nil)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,222 @@
1
+ module Steep
2
+ module TypeInference
3
+ class SendArgs
4
+ attr_reader :args
5
+ attr_reader :kw_args
6
+
7
+ def initialize(args:, kw_args:)
8
+ @args = args
9
+ @kw_args = kw_args
10
+ end
11
+
12
+ def self.from_nodes(nodes)
13
+ args = []
14
+ last_hash = nil
15
+
16
+ nodes.each do |node|
17
+ if last_hash
18
+ args << last_hash
19
+ last_hash = nil
20
+ end
21
+
22
+ case node.type
23
+ when :hash
24
+ last_hash = node
25
+ else
26
+ args << node
27
+ end
28
+ end
29
+
30
+ if last_hash
31
+ unless kw_args?(last_hash)
32
+ args << last_hash
33
+ last_hash = nil
34
+ end
35
+ end
36
+
37
+ new(args: args, kw_args: last_hash)
38
+ end
39
+
40
+ def self.kw_args?(node)
41
+ node.children.all? do |child|
42
+ case child.type
43
+ when :pair
44
+ child.children[0].type == :sym
45
+ when :kwsplat
46
+ true
47
+ end
48
+ end
49
+ end
50
+
51
+ def each_keyword_arg
52
+ if block_given?
53
+ if kw_args
54
+ kw_args.children.each do |node|
55
+ if node.type == :pair
56
+ yield node
57
+ end
58
+ end
59
+ end
60
+ else
61
+ enum_for :each_keyword_arg
62
+ end
63
+ end
64
+
65
+ def kwsplat_nodes
66
+ if kw_args
67
+ kw_args.children.select do |node|
68
+ node.type == :kwsplat
69
+ end
70
+ else
71
+ []
72
+ end
73
+ end
74
+
75
+ def zip(params)
76
+ Set.new(
77
+ [].tap do |pairs|
78
+ consumed_keywords = Set.new
79
+ rest_types = []
80
+
81
+ params.required_keywords.each do |name, type|
82
+ if (node = each_keyword_arg.find {|pair| pair.children[0].children[0] == name })
83
+ pairs << [node.children[1], type]
84
+ consumed_keywords << name
85
+ else
86
+ if kwsplat_nodes.any?
87
+ rest_types << type
88
+ else
89
+ return
90
+ end
91
+ end
92
+ end
93
+
94
+ params.optional_keywords.each do |name, type|
95
+ if (node = each_keyword_arg.find {|pair| pair.children[0].children[0] == name })
96
+ pairs << [node.children[1], type]
97
+ consumed_keywords << name
98
+ else
99
+ if kwsplat_nodes.any?
100
+ rest_types << type
101
+ end
102
+ end
103
+ end
104
+
105
+ if params.rest_keywords
106
+ each_keyword_arg do |pair|
107
+ name = pair.children[0].children[0]
108
+ node = pair.children[1]
109
+
110
+ unless consumed_keywords.include?(name)
111
+ pairs << [node, params.rest_keywords]
112
+ end
113
+ end
114
+
115
+ if kwsplat_nodes.any?
116
+ pairs << [kw_args,
117
+ AST::Types::Name.new_instance(
118
+ name: "::Hash",
119
+ args: [
120
+ AST::Types::Name.new_instance(name: "::Symbol"),
121
+ AST::Types::Union.build(types: rest_types + [params.rest_keywords])
122
+ ]
123
+ )]
124
+ end
125
+ end
126
+
127
+ if params.has_keyword?
128
+ if !params.rest_keywords
129
+ if kwsplat_nodes.empty?
130
+ if each_keyword_arg.any? {|pair| !consumed_keywords.include?(pair.children[0].children[0]) }
131
+ return
132
+ end
133
+ end
134
+ end
135
+ end
136
+
137
+ args = self.args.dup
138
+ unless params.has_keyword?
139
+ args << kw_args if kw_args
140
+ end
141
+
142
+ arg_types = {}
143
+
144
+ params.required.each do |param|
145
+ if args.any?
146
+ next_arg(args) do |arg|
147
+ save_arg_type(arg, param, arg_types)
148
+ end
149
+ consume_arg(args)
150
+ else
151
+ return
152
+ end
153
+ end
154
+
155
+ params.optional.each do |param|
156
+ next_arg(args) do |arg|
157
+ save_arg_type(arg, param, arg_types)
158
+ end
159
+ consume_arg(args)
160
+ end
161
+
162
+ if args.any?
163
+ if params.rest
164
+ args.each do |arg|
165
+ save_arg_type(arg, params.rest, arg_types)
166
+ end
167
+ else
168
+ if args.none? {|arg| arg.type == :splat }
169
+ return
170
+ end
171
+ end
172
+ end
173
+
174
+ (self.args + [kw_args].compact).each do |arg|
175
+ types = arg_types[arg.object_id]
176
+
177
+ if types
178
+ if arg.type == :splat
179
+ type = AST::Types::Name.new_instance(name: "::Array", args: [AST::Types::Union.build(types: types)])
180
+ else
181
+ type = AST::Types::Union.build(types: types)
182
+ end
183
+ pairs << [arg, type]
184
+ end
185
+ end
186
+ end
187
+ )
188
+ end
189
+
190
+ def save_arg_type(arg, type, hash)
191
+ if hash.key?(arg.object_id)
192
+ types = hash[arg.object_id]
193
+ else
194
+ types = hash[arg.object_id] = []
195
+ end
196
+
197
+ types << type
198
+ end
199
+
200
+ def next_arg(args)
201
+ if args.any?
202
+ case args[0].type
203
+ when :splat
204
+ args.each do |arg|
205
+ yield arg
206
+ end
207
+ else
208
+ yield args[0]
209
+ end
210
+ end
211
+ end
212
+
213
+ def consume_arg(args)
214
+ if args.any?
215
+ unless args[0].type == :splat
216
+ args.shift
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,226 @@
1
+ module Steep
2
+ module TypeInference
3
+ class TypeEnv
4
+ attr_reader :subtyping
5
+ attr_reader :lvar_types
6
+ attr_reader :const_types
7
+ attr_reader :gvar_types
8
+ attr_reader :ivar_types
9
+ attr_reader :const_env
10
+
11
+ def initialize(subtyping:, const_env:)
12
+ @subtyping = subtyping
13
+ @lvar_types = {}
14
+ @const_types = {}
15
+ @gvar_types = {}
16
+ @ivar_types = {}
17
+ @const_env = const_env
18
+ end
19
+
20
+ def initialize_copy(other)
21
+ @subtyping = other.subtyping
22
+ @lvar_types = other.lvar_types.dup
23
+ @const_types = other.const_types.dup
24
+ @gvar_types = other.gvar_types.dup
25
+ @ivar_types = other.ivar_types.dup
26
+ @const_env = other.const_env
27
+ end
28
+
29
+ def self.build(annotations:, signatures:, subtyping:, const_env:)
30
+ new(subtyping: subtyping, const_env: const_env).tap do |env|
31
+ annotations.var_types.each do |name, annot|
32
+ env.set(lvar: name, type: subtyping.builder.absolute_type(annot.type, current: const_env.current_namespace))
33
+ end
34
+ annotations.ivar_types.each do |name, type|
35
+ env.set(ivar: name, type: subtyping.builder.absolute_type(type, current: const_env.current_namespace))
36
+ end
37
+ annotations.const_types.each do |name, type|
38
+ env.set(const: name, type: subtyping.builder.absolute_type(type, current: const_env.current_namespace))
39
+ end
40
+ signatures.globals.each do |name, annot|
41
+ type = subtyping.builder.absolute_type(annot.type, current: nil)
42
+ env.set(gvar: name, type: type)
43
+ end
44
+ end
45
+ end
46
+
47
+ def with_annotations(lvar_types: {}, ivar_types: {}, const_types: {}, gvar_types: {}, &block)
48
+ dup.tap do |env|
49
+ merge!(original_env: env.lvar_types, override_env: lvar_types, &block)
50
+ merge!(original_env: env.ivar_types, override_env: ivar_types, &block)
51
+ merge!(original_env: env.gvar_types, override_env: gvar_types, &block)
52
+
53
+ const_types.each do |name, annotated_type|
54
+ original_type = self.const_types[name] || const_env.lookup(name)
55
+ if original_type
56
+ assert_annotation name, original_type: original_type, annotated_type: annotated_type, &block
57
+ end
58
+ env.const_types[name] = annotated_type
59
+ end
60
+ end
61
+ end
62
+
63
+ def join!(envs)
64
+ lvars = {}
65
+
66
+ common_vars = envs.map {|env| Set.new(env.lvar_types.keys) }.inject {|a, b| a & b }
67
+
68
+ envs.each do |env|
69
+ env.lvar_types.each do |name, type|
70
+ unless lvar_types.key?(name)
71
+ lvars[name] = [] unless lvars[name]
72
+ lvars[name] << type
73
+ end
74
+ end
75
+ end
76
+
77
+ lvars.each do |name, types|
78
+ if lvar_types.key?(name) || common_vars.member?(name)
79
+ set(lvar: name, type: AST::Types::Union.build(types: types))
80
+ else
81
+ set(lvar: name, type: AST::Types::Union.build(types: types + [AST::Types::Name.new_instance(name: "::NilClass")]))
82
+ end
83
+ end
84
+ end
85
+
86
+ # @type method assert: (const: ModuleName) { () -> void } -> AST::Type
87
+ # | (gvar: Symbol) { () -> void } -> AST::Type
88
+ # | (ivar: Symbol) { () -> void } -> AST::Type
89
+ # | (lvar: Symbol) { () -> AST::Type | nil } -> AST::Type
90
+ def get(lvar: nil, const: nil, gvar: nil, ivar: nil)
91
+ case
92
+ when lvar
93
+ lvar_name(lvar).yield_self do |name|
94
+ if lvar_types.key?(name)
95
+ lvar_types[name]
96
+ else
97
+ ty = yield
98
+ lvar_types[name] = ty || AST::Types::Any.new
99
+ end
100
+ end
101
+ when const
102
+ if const_types.key?(const)
103
+ const_types[const]
104
+ else
105
+ const_env.lookup(const).yield_self do |type|
106
+ if type
107
+ type
108
+ else
109
+ yield
110
+ AST::Types::Any.new
111
+ end
112
+ end
113
+ end
114
+ else
115
+ lookup_dictionary(ivar: ivar, gvar: gvar) do |var_name, dictionary|
116
+ if dictionary.key?(var_name)
117
+ dictionary[var_name]
118
+ else
119
+ yield
120
+ AST::Types::Any.new
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ def set(lvar: nil, const: nil, gvar: nil, ivar: nil, type:)
127
+ case
128
+ when lvar
129
+ lvar_name(lvar).yield_self do |name|
130
+ lvar_types[name] = type
131
+ end
132
+ when const
133
+ const_types[const] = type
134
+ else
135
+ lookup_dictionary(ivar: ivar, gvar: gvar) do |var_name, dictionary|
136
+ dictionary[var_name] = type
137
+ end
138
+ end
139
+ end
140
+
141
+ # @type method assign: (const: ModuleName, type: AST::Type) { (Subtyping::Result::Failure | nil) -> void } -> AST::Type
142
+ # | (gvar: Symbol, type: AST::Type) { (Subtyping::Result::Failure | nil) -> void } -> AST::Type
143
+ # | (ivar: Symbol, type: AST::Type) { (Subtyping::Result::Failure | nil) -> void } -> AST::Type
144
+ # | (lvar: Symbol | LabeledName, type: AST::Type) { (Subtyping::Result::Failure) -> void } -> AST::Type
145
+ def assign(lvar: nil, const: nil, gvar: nil, ivar: nil, type:, &block)
146
+ case
147
+ when lvar
148
+ yield_self do
149
+ name = lvar_name(lvar)
150
+ var_type = lvar_types[name]
151
+ if var_type
152
+ assert_assign(var_type: var_type, lhs_type: type, &block)
153
+ else
154
+ lvar_types[name] = type
155
+ end
156
+ end
157
+ when const
158
+ yield_self do
159
+ const_type = const_types[const] || const_env.lookup(const)
160
+ if const_type
161
+ assert_assign(var_type: const_type, lhs_type: type, &block)
162
+ else
163
+ yield nil
164
+ AST::Types::Any.new
165
+ end
166
+ end
167
+ else
168
+ lookup_dictionary(ivar: ivar, gvar: gvar) do |var_name, dictionary|
169
+ if dictionary.key?(var_name)
170
+ assert_assign(var_type: dictionary[var_name], lhs_type: type, &block)
171
+ else
172
+ yield nil
173
+ AST::Types::Any.new
174
+ end
175
+ end
176
+ end
177
+ end
178
+
179
+ def lookup_dictionary(ivar:, gvar:)
180
+ case
181
+ when ivar
182
+ yield ivar, ivar_types
183
+ when gvar
184
+ yield gvar, gvar_types
185
+ end
186
+ end
187
+
188
+ def lvar_name(lvar)
189
+ case lvar
190
+ when Symbol
191
+ lvar
192
+ when ASTUtils::Labeling::LabeledName
193
+ lvar.name
194
+ end
195
+ end
196
+
197
+ def assert_assign(var_type:, lhs_type:)
198
+ relation = Subtyping::Relation.new(sub_type: lhs_type, super_type: var_type)
199
+ constraints = Subtyping::Constraints.new(unknowns: Set.new)
200
+
201
+ subtyping.check(relation, constraints: constraints).else do |result|
202
+ yield result
203
+ end
204
+
205
+ var_type
206
+ end
207
+
208
+ def merge!(original_env:, override_env:, &block)
209
+ original_env.merge!(override_env) do |name, original_type, override_type|
210
+ assert_annotation name, annotated_type: override_type, original_type: original_type, &block
211
+ end
212
+ end
213
+
214
+ def assert_annotation(name, annotated_type:, original_type:)
215
+ relation = Subtyping::Relation.new(sub_type: annotated_type, super_type: original_type)
216
+ constraints = Subtyping::Constraints.new(unknowns: Set.new)
217
+
218
+ subtyping.check(relation, constraints: constraints).else do |result|
219
+ yield name, relation, result
220
+ end
221
+
222
+ annotated_type
223
+ end
224
+ end
225
+ end
226
+ end
@@ -12,21 +12,27 @@ module Steep
12
12
  end
13
13
 
14
14
  def hash
15
- name.hash
15
+ self.class.hash ^ name.hash
16
16
  end
17
17
 
18
- def eql?(other)
19
- self == other
20
- end
18
+ alias eql? ==
21
19
 
22
20
  def to_s
23
21
  name.to_s
24
22
  end
23
+
24
+ def map_module_name
25
+ self.class.new(name: yield(name))
26
+ end
25
27
  end
26
28
 
27
- class Interface < Base; end
29
+ class Interface < Base
30
+ def map_module_name
31
+ self
32
+ end
33
+ end
28
34
 
29
- class Module < Base
35
+ class Class < Base
30
36
  attr_reader :constructor
31
37
 
32
38
  def to_s
@@ -39,7 +45,7 @@ module Steep
39
45
  " noconstructor"
40
46
  end
41
47
 
42
- "#{name}.module#{k}"
48
+ "#{name}.class#{k}"
43
49
  end
44
50
 
45
51
  def initialize(name:, constructor:)
@@ -51,6 +57,10 @@ module Steep
51
57
  other.is_a?(self.class) && other.name == name && other.constructor == constructor
52
58
  end
53
59
 
60
+ def hash
61
+ self.class.hash ^ name.hash ^ constructor.hash
62
+ end
63
+
54
64
  NOTHING = Object.new
55
65
 
56
66
  def updated(constructor: NOTHING)
@@ -60,6 +70,16 @@ module Steep
60
70
 
61
71
  self.class.new(name: name, constructor: constructor)
62
72
  end
73
+
74
+ def map_module_name
75
+ self.class.new(name: yield(name), constructor: constructor)
76
+ end
77
+ end
78
+
79
+ class Module < Base
80
+ def to_s
81
+ "#{name}.module"
82
+ end
63
83
  end
64
84
 
65
85
  class Instance < Base; end
data/lib/steep/typing.rb CHANGED
@@ -23,6 +23,10 @@ module Steep
23
23
  type
24
24
  end
25
25
 
26
+ def has_type?(node)
27
+ typing.key?(node.__id__)
28
+ end
29
+
26
30
  def add_var_type(variable, type)
27
31
  if var_typing.key?(variable)
28
32
  unless var_typing[variable] == type
data/lib/steep/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "0.1.0.pre2"
2
+ VERSION = "0.1.0"
3
3
  end