steep 0.13.0 → 0.16.2

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 (214) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +0 -3
  3. data/CHANGELOG.md +28 -0
  4. data/Rakefile +0 -13
  5. data/bin/setup +0 -2
  6. data/bin/smoke_runner.rb +0 -1
  7. data/exe/steep +0 -1
  8. data/lib/steep.rb +33 -1
  9. data/lib/steep/annotation_parser.rb +4 -4
  10. data/lib/steep/ast/buffer.rb +11 -7
  11. data/lib/steep/ast/builtin.rb +8 -0
  12. data/lib/steep/ast/types/factory.rb +124 -89
  13. data/lib/steep/cli.rb +16 -1
  14. data/lib/steep/drivers/annotations.rb +1 -1
  15. data/lib/steep/drivers/check.rb +20 -4
  16. data/lib/steep/drivers/init.rb +5 -5
  17. data/lib/steep/drivers/langserver.rb +13 -287
  18. data/lib/steep/drivers/utils/driver_helper.rb +1 -1
  19. data/lib/steep/drivers/vendor.rb +2 -2
  20. data/lib/steep/drivers/watch.rb +97 -85
  21. data/lib/steep/drivers/worker.rb +51 -0
  22. data/lib/steep/project.rb +9 -5
  23. data/lib/steep/project/completion_provider.rb +298 -0
  24. data/lib/steep/project/dsl.rb +14 -0
  25. data/lib/steep/project/file.rb +54 -47
  26. data/lib/steep/project/hover_content.rb +17 -8
  27. data/lib/steep/project/options.rb +25 -3
  28. data/lib/steep/project/target.rb +40 -24
  29. data/lib/steep/server/base_worker.rb +56 -0
  30. data/lib/steep/server/code_worker.rb +151 -0
  31. data/lib/steep/server/interaction_worker.rb +281 -0
  32. data/lib/steep/server/master.rb +196 -0
  33. data/lib/steep/server/signature_worker.rb +148 -0
  34. data/lib/steep/server/utils.rb +36 -0
  35. data/lib/steep/server/worker_process.rb +62 -0
  36. data/lib/steep/signature/errors.rb +1 -1
  37. data/lib/steep/signature/validator.rb +13 -13
  38. data/lib/steep/source.rb +1 -1
  39. data/lib/steep/type_construction.rb +1004 -727
  40. data/lib/steep/type_inference/constant_env.rb +3 -11
  41. data/lib/steep/type_inference/context.rb +8 -3
  42. data/lib/steep/type_inference/context_array.rb +111 -0
  43. data/lib/steep/type_inference/local_variable_type_env.rb +226 -0
  44. data/lib/steep/type_inference/logic.rb +130 -0
  45. data/lib/steep/type_inference/type_env.rb +5 -69
  46. data/lib/steep/typing.rb +91 -23
  47. data/lib/steep/version.rb +1 -1
  48. data/smoke/alias/Steepfile +1 -0
  49. data/smoke/alias/a.rb +1 -1
  50. data/smoke/and/Steepfile +1 -0
  51. data/smoke/array/Steepfile +1 -0
  52. data/smoke/array/b.rb +0 -2
  53. data/smoke/block/Steepfile +1 -0
  54. data/smoke/case/Steepfile +1 -0
  55. data/smoke/class/Steepfile +1 -0
  56. data/smoke/const/Steepfile +1 -0
  57. data/smoke/dstr/Steepfile +1 -0
  58. data/smoke/ensure/Steepfile +1 -0
  59. data/smoke/enumerator/Steepfile +1 -0
  60. data/smoke/extension/Steepfile +1 -0
  61. data/smoke/extension/c.rb +1 -0
  62. data/smoke/hash/Steepfile +1 -0
  63. data/smoke/hello/Steepfile +1 -0
  64. data/smoke/if/Steepfile +1 -0
  65. data/smoke/if/a.rb +1 -1
  66. data/smoke/implements/Steepfile +1 -0
  67. data/smoke/initialize/Steepfile +1 -0
  68. data/smoke/integer/Steepfile +1 -0
  69. data/smoke/interface/Steepfile +1 -0
  70. data/smoke/kwbegin/Steepfile +1 -0
  71. data/smoke/lambda/Steepfile +1 -0
  72. data/smoke/literal/Steepfile +1 -0
  73. data/smoke/map/Steepfile +1 -0
  74. data/smoke/method/Steepfile +1 -0
  75. data/smoke/module/Steepfile +1 -0
  76. data/smoke/regexp/Steepfile +1 -0
  77. data/smoke/regexp/b.rb +4 -4
  78. data/smoke/regression/Steepfile +1 -0
  79. data/smoke/rescue/Steepfile +1 -0
  80. data/smoke/rescue/a.rb +1 -1
  81. data/smoke/self/Steepfile +1 -0
  82. data/smoke/skip/Steepfile +1 -0
  83. data/smoke/stdout/Steepfile +1 -0
  84. data/smoke/super/Steepfile +1 -0
  85. data/smoke/type_case/Steepfile +1 -0
  86. data/smoke/yield/Steepfile +1 -0
  87. data/steep.gemspec +8 -8
  88. metadata +38 -138
  89. data/exe/rbs +0 -3
  90. data/exe/ruby-signature +0 -3
  91. data/vendor/ruby-signature/.github/workflows/ruby.yml +0 -27
  92. data/vendor/ruby-signature/.gitignore +0 -12
  93. data/vendor/ruby-signature/.rubocop.yml +0 -15
  94. data/vendor/ruby-signature/BSDL +0 -22
  95. data/vendor/ruby-signature/COPYING +0 -56
  96. data/vendor/ruby-signature/Gemfile +0 -6
  97. data/vendor/ruby-signature/README.md +0 -93
  98. data/vendor/ruby-signature/Rakefile +0 -66
  99. data/vendor/ruby-signature/bin/annotate-with-rdoc +0 -156
  100. data/vendor/ruby-signature/bin/console +0 -14
  101. data/vendor/ruby-signature/bin/query-rdoc +0 -103
  102. data/vendor/ruby-signature/bin/setup +0 -10
  103. data/vendor/ruby-signature/bin/sort +0 -88
  104. data/vendor/ruby-signature/bin/test_runner.rb +0 -17
  105. data/vendor/ruby-signature/docs/CONTRIBUTING.md +0 -97
  106. data/vendor/ruby-signature/docs/sigs.md +0 -148
  107. data/vendor/ruby-signature/docs/stdlib.md +0 -152
  108. data/vendor/ruby-signature/docs/syntax.md +0 -528
  109. data/vendor/ruby-signature/exe/rbs +0 -3
  110. data/vendor/ruby-signature/exe/ruby-signature +0 -7
  111. data/vendor/ruby-signature/lib/ruby/signature.rb +0 -64
  112. data/vendor/ruby-signature/lib/ruby/signature/ast/annotation.rb +0 -29
  113. data/vendor/ruby-signature/lib/ruby/signature/ast/comment.rb +0 -29
  114. data/vendor/ruby-signature/lib/ruby/signature/ast/declarations.rb +0 -391
  115. data/vendor/ruby-signature/lib/ruby/signature/ast/members.rb +0 -364
  116. data/vendor/ruby-signature/lib/ruby/signature/buffer.rb +0 -52
  117. data/vendor/ruby-signature/lib/ruby/signature/builtin_names.rb +0 -54
  118. data/vendor/ruby-signature/lib/ruby/signature/cli.rb +0 -534
  119. data/vendor/ruby-signature/lib/ruby/signature/constant.rb +0 -28
  120. data/vendor/ruby-signature/lib/ruby/signature/constant_table.rb +0 -152
  121. data/vendor/ruby-signature/lib/ruby/signature/definition.rb +0 -172
  122. data/vendor/ruby-signature/lib/ruby/signature/definition_builder.rb +0 -921
  123. data/vendor/ruby-signature/lib/ruby/signature/environment.rb +0 -283
  124. data/vendor/ruby-signature/lib/ruby/signature/environment_loader.rb +0 -138
  125. data/vendor/ruby-signature/lib/ruby/signature/environment_walker.rb +0 -126
  126. data/vendor/ruby-signature/lib/ruby/signature/errors.rb +0 -189
  127. data/vendor/ruby-signature/lib/ruby/signature/location.rb +0 -104
  128. data/vendor/ruby-signature/lib/ruby/signature/method_type.rb +0 -125
  129. data/vendor/ruby-signature/lib/ruby/signature/namespace.rb +0 -93
  130. data/vendor/ruby-signature/lib/ruby/signature/parser.y +0 -1343
  131. data/vendor/ruby-signature/lib/ruby/signature/prototype/rb.rb +0 -441
  132. data/vendor/ruby-signature/lib/ruby/signature/prototype/rbi.rb +0 -579
  133. data/vendor/ruby-signature/lib/ruby/signature/prototype/runtime.rb +0 -383
  134. data/vendor/ruby-signature/lib/ruby/signature/substitution.rb +0 -48
  135. data/vendor/ruby-signature/lib/ruby/signature/test.rb +0 -28
  136. data/vendor/ruby-signature/lib/ruby/signature/test/errors.rb +0 -63
  137. data/vendor/ruby-signature/lib/ruby/signature/test/hook.rb +0 -290
  138. data/vendor/ruby-signature/lib/ruby/signature/test/setup.rb +0 -58
  139. data/vendor/ruby-signature/lib/ruby/signature/test/spy.rb +0 -324
  140. data/vendor/ruby-signature/lib/ruby/signature/test/test_helper.rb +0 -185
  141. data/vendor/ruby-signature/lib/ruby/signature/test/type_check.rb +0 -256
  142. data/vendor/ruby-signature/lib/ruby/signature/type_name.rb +0 -72
  143. data/vendor/ruby-signature/lib/ruby/signature/types.rb +0 -932
  144. data/vendor/ruby-signature/lib/ruby/signature/variance_calculator.rb +0 -140
  145. data/vendor/ruby-signature/lib/ruby/signature/vendorer.rb +0 -49
  146. data/vendor/ruby-signature/lib/ruby/signature/version.rb +0 -5
  147. data/vendor/ruby-signature/lib/ruby/signature/writer.rb +0 -271
  148. data/vendor/ruby-signature/ruby-signature.gemspec +0 -45
  149. data/vendor/ruby-signature/stdlib/abbrev/abbrev.rbs +0 -3
  150. data/vendor/ruby-signature/stdlib/base64/base64.rbs +0 -15
  151. data/vendor/ruby-signature/stdlib/builtin/array.rbs +0 -1997
  152. data/vendor/ruby-signature/stdlib/builtin/basic_object.rbs +0 -280
  153. data/vendor/ruby-signature/stdlib/builtin/binding.rbs +0 -177
  154. data/vendor/ruby-signature/stdlib/builtin/builtin.rbs +0 -35
  155. data/vendor/ruby-signature/stdlib/builtin/class.rbs +0 -145
  156. data/vendor/ruby-signature/stdlib/builtin/comparable.rbs +0 -116
  157. data/vendor/ruby-signature/stdlib/builtin/complex.rbs +0 -400
  158. data/vendor/ruby-signature/stdlib/builtin/constants.rbs +0 -37
  159. data/vendor/ruby-signature/stdlib/builtin/data.rbs +0 -5
  160. data/vendor/ruby-signature/stdlib/builtin/deprecated.rbs +0 -2
  161. data/vendor/ruby-signature/stdlib/builtin/dir.rbs +0 -419
  162. data/vendor/ruby-signature/stdlib/builtin/encoding.rbs +0 -606
  163. data/vendor/ruby-signature/stdlib/builtin/enumerable.rbs +0 -404
  164. data/vendor/ruby-signature/stdlib/builtin/enumerator.rbs +0 -260
  165. data/vendor/ruby-signature/stdlib/builtin/errno.rbs +0 -781
  166. data/vendor/ruby-signature/stdlib/builtin/errors.rbs +0 -582
  167. data/vendor/ruby-signature/stdlib/builtin/exception.rbs +0 -193
  168. data/vendor/ruby-signature/stdlib/builtin/false_class.rbs +0 -40
  169. data/vendor/ruby-signature/stdlib/builtin/fiber.rbs +0 -68
  170. data/vendor/ruby-signature/stdlib/builtin/fiber_error.rbs +0 -12
  171. data/vendor/ruby-signature/stdlib/builtin/file.rbs +0 -476
  172. data/vendor/ruby-signature/stdlib/builtin/file_test.rbs +0 -59
  173. data/vendor/ruby-signature/stdlib/builtin/float.rbs +0 -696
  174. data/vendor/ruby-signature/stdlib/builtin/gc.rbs +0 -121
  175. data/vendor/ruby-signature/stdlib/builtin/hash.rbs +0 -1029
  176. data/vendor/ruby-signature/stdlib/builtin/integer.rbs +0 -710
  177. data/vendor/ruby-signature/stdlib/builtin/io.rbs +0 -683
  178. data/vendor/ruby-signature/stdlib/builtin/kernel.rbs +0 -574
  179. data/vendor/ruby-signature/stdlib/builtin/marshal.rbs +0 -135
  180. data/vendor/ruby-signature/stdlib/builtin/match_data.rbs +0 -141
  181. data/vendor/ruby-signature/stdlib/builtin/math.rbs +0 -66
  182. data/vendor/ruby-signature/stdlib/builtin/method.rbs +0 -182
  183. data/vendor/ruby-signature/stdlib/builtin/module.rbs +0 -248
  184. data/vendor/ruby-signature/stdlib/builtin/nil_class.rbs +0 -82
  185. data/vendor/ruby-signature/stdlib/builtin/numeric.rbs +0 -409
  186. data/vendor/ruby-signature/stdlib/builtin/object.rbs +0 -824
  187. data/vendor/ruby-signature/stdlib/builtin/proc.rbs +0 -426
  188. data/vendor/ruby-signature/stdlib/builtin/process.rbs +0 -354
  189. data/vendor/ruby-signature/stdlib/builtin/random.rbs +0 -93
  190. data/vendor/ruby-signature/stdlib/builtin/range.rbs +0 -226
  191. data/vendor/ruby-signature/stdlib/builtin/rational.rbs +0 -424
  192. data/vendor/ruby-signature/stdlib/builtin/rb_config.rbs +0 -10
  193. data/vendor/ruby-signature/stdlib/builtin/regexp.rbs +0 -131
  194. data/vendor/ruby-signature/stdlib/builtin/ruby_vm.rbs +0 -14
  195. data/vendor/ruby-signature/stdlib/builtin/signal.rbs +0 -55
  196. data/vendor/ruby-signature/stdlib/builtin/string.rbs +0 -770
  197. data/vendor/ruby-signature/stdlib/builtin/string_io.rbs +0 -13
  198. data/vendor/ruby-signature/stdlib/builtin/struct.rbs +0 -40
  199. data/vendor/ruby-signature/stdlib/builtin/symbol.rbs +0 -230
  200. data/vendor/ruby-signature/stdlib/builtin/thread.rbs +0 -1112
  201. data/vendor/ruby-signature/stdlib/builtin/thread_group.rbs +0 -23
  202. data/vendor/ruby-signature/stdlib/builtin/time.rbs +0 -739
  203. data/vendor/ruby-signature/stdlib/builtin/trace_point.rbs +0 -91
  204. data/vendor/ruby-signature/stdlib/builtin/true_class.rbs +0 -46
  205. data/vendor/ruby-signature/stdlib/builtin/unbound_method.rbs +0 -159
  206. data/vendor/ruby-signature/stdlib/builtin/warning.rbs +0 -17
  207. data/vendor/ruby-signature/stdlib/erb/erb.rbs +0 -18
  208. data/vendor/ruby-signature/stdlib/find/find.rbs +0 -44
  209. data/vendor/ruby-signature/stdlib/pathname/pathname.rbs +0 -21
  210. data/vendor/ruby-signature/stdlib/prime/integer-extension.rbs +0 -23
  211. data/vendor/ruby-signature/stdlib/prime/prime.rbs +0 -188
  212. data/vendor/ruby-signature/stdlib/securerandom/securerandom.rbs +0 -9
  213. data/vendor/ruby-signature/stdlib/set/set.rbs +0 -77
  214. data/vendor/ruby-signature/stdlib/tmpdir/tmpdir.rbs +0 -53
@@ -12,29 +12,21 @@ module Steep
12
12
  @cache = {}
13
13
  @factory = factory
14
14
  @context = context
15
- @table = Ruby::Signature::ConstantTable.new(builder: factory.definition_builder)
16
- end
17
-
18
- def namespace
19
- @namespace ||= if context
20
- context.namespace.append(context.name)
21
- else
22
- AST::Namespace.root
23
- end
15
+ @table = RBS::ConstantTable.new(builder: factory.definition_builder)
24
16
  end
25
17
 
26
18
  def lookup(name)
27
19
  cache[name] ||= begin
28
20
  constant = table.resolve_constant_reference(
29
21
  factory.type_name_1(name),
30
- context: factory.namespace_1(namespace)
22
+ context: context.map {|namespace| factory.namespace_1(namespace) }
31
23
  )
32
24
 
33
25
  if constant
34
26
  factory.type(constant.type)
35
27
  end
36
28
  rescue => exn
37
- Steep.logger.error "Looking up a constant failed: name=#{name}, context=#{context}, error=#{exn.inspect}"
29
+ Steep.logger.error "Looking up a constant failed: name=#{name}, context=[#{context.join(", ")}], error=#{exn.inspect}"
38
30
  nil
39
31
  end
40
32
  end
@@ -48,6 +48,7 @@ module Steep
48
48
  attr_reader :defined_module_methods
49
49
  attr_reader :const_env
50
50
  attr_reader :implement_name
51
+ attr_reader :namespaces
51
52
  attr_reader :current_namespace
52
53
  attr_reader :class_name
53
54
  attr_reader :instance_definition
@@ -77,14 +78,16 @@ module Steep
77
78
  attr_reader :module_context
78
79
  attr_reader :self_type
79
80
  attr_reader :type_env
81
+ attr_reader :lvar_env
80
82
 
81
- def initialize(method_context:, block_context:, break_context:, module_context:, self_type:, type_env:)
83
+ def initialize(method_context:, block_context:, break_context:, module_context:, self_type:, type_env:, lvar_env:)
82
84
  @method_context = method_context
83
85
  @block_context = block_context
84
86
  @break_context = break_context
85
87
  @module_context = module_context
86
88
  @self_type = self_type
87
89
  @type_env = type_env
90
+ @lvar_env = lvar_env
88
91
  end
89
92
 
90
93
  def with(method_context: self.method_context,
@@ -92,14 +95,16 @@ module Steep
92
95
  break_context: self.break_context,
93
96
  module_context: self.module_context,
94
97
  self_type: self.self_type,
95
- type_env: self.type_env)
98
+ type_env: self.type_env,
99
+ lvar_env: self.lvar_env)
96
100
  self.class.new(
97
101
  method_context: method_context,
98
102
  block_context: block_context,
99
103
  break_context: break_context,
100
104
  module_context: module_context,
101
105
  self_type: self_type,
102
- type_env: type_env
106
+ type_env: type_env,
107
+ lvar_env: lvar_env
103
108
  )
104
109
  end
105
110
  end
@@ -0,0 +1,111 @@
1
+ module Steep
2
+ module TypeInference
3
+ class ContextArray
4
+ class Entry
5
+ attr_reader :range, :context, :sub_entries
6
+
7
+ def initialize(range:, context:)
8
+ @range = range
9
+ @context = context
10
+ @sub_entries = Set[].compare_by_identity
11
+ end
12
+ end
13
+
14
+ attr_reader :buffer
15
+ attr_reader :root
16
+
17
+ def initialize(buffer:, context:, range: 0..buffer.content.size)
18
+ @buffer = buffer
19
+ @root = Entry.new(range: range, context: context)
20
+ end
21
+
22
+ def range
23
+ root.range
24
+ end
25
+
26
+ def self.from_source(source:, range: nil, context: nil)
27
+ content = if source.node
28
+ source.node.location.expression.source_buffer.source
29
+ else
30
+ ""
31
+ end
32
+ buffer = AST::Buffer.new(name: source.path, content: content)
33
+ new(buffer: buffer, context: context, range: range || 0..buffer.content.size)
34
+ end
35
+
36
+ def insert_context(range, context:, entry: self.root)
37
+ entry.sub_entries.each do |sub|
38
+ next if sub.range.begin < range.begin && range.end <= sub.range.end
39
+ next if range.begin < sub.range.begin && sub.range.end <= range.end
40
+ next if range.end <= sub.range.begin
41
+ next if sub.range.end <= range.begin
42
+
43
+ raise "Range crossing: sub range=#{sub.range}, new range=#{range}"
44
+ end
45
+
46
+ sup = entry.sub_entries.find do |sub|
47
+ sub.range.begin < range.begin && range.end <= sub.range.end
48
+ end
49
+
50
+ if sup
51
+ insert_context(range, context: context, entry: sup)
52
+ else
53
+ subs = entry.sub_entries.select do |sub|
54
+ range.begin < sub.range.begin && sub.range.end <= range.end
55
+ end
56
+
57
+ new_entry = Entry.new(range: range, context: context)
58
+ entry.sub_entries.subtract(subs)
59
+ new_entry.sub_entries.merge(subs)
60
+ entry.sub_entries << new_entry
61
+ end
62
+ end
63
+
64
+ def each_entry
65
+ if block_given?
66
+ es = [root]
67
+
68
+ until es.empty?
69
+ e = es.pop
70
+ es.push(*e.sub_entries.to_a)
71
+
72
+ yield e
73
+ end
74
+ else
75
+ enum_for :each_entry
76
+ end
77
+ end
78
+
79
+ def context_at(index, entry: self.root)
80
+ return nil if index < entry.range.begin || entry.range.end < index
81
+
82
+ sub = entry.sub_entries.find do |sub|
83
+ sub.range.begin <= index && index <= sub.range.end
84
+ end
85
+
86
+ if sub
87
+ context_at(index, entry: sub)
88
+ else
89
+ entry.context
90
+ end
91
+ end
92
+
93
+ def [](index)
94
+ context_at(index)
95
+ end
96
+
97
+ def at(line:, column:)
98
+ pos = buffer.loc_to_pos([line, column])
99
+ self[pos]
100
+ end
101
+
102
+ def merge(subtree)
103
+ subtree.each_entry do |entry|
104
+ if entry.context
105
+ insert_context entry.range, context: entry.context
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,226 @@
1
+ module Steep
2
+ module TypeInference
3
+ class LocalVariableTypeEnv
4
+ attr_reader :subtyping
5
+ attr_reader :self_type
6
+
7
+ class Entry
8
+ attr_reader :type
9
+ attr_reader :annotations
10
+ attr_reader :nodes
11
+
12
+ def initialize(type:, annotations: [], nodes: [])
13
+ @type = type
14
+ @annotations = Set.new(annotations)
15
+ @nodes = Set[].compare_by_identity.merge(nodes)
16
+ end
17
+
18
+ def update(type: self.type, annotations: self.annotations, nodes: self.nodes)
19
+ Entry.new(type: type, annotations: annotations, nodes: nodes)
20
+ end
21
+
22
+ def ==(other)
23
+ other.is_a?(Entry) &&
24
+ other.type == type &&
25
+ other.annotations == annotations &&
26
+ other.nodes == nodes
27
+ end
28
+
29
+ def +(other)
30
+ self.class.new(type: AST::Types::Union.build(types: [type, other.type]),
31
+ annotations: annotations + other.annotations,
32
+ nodes: nodes + other.nodes)
33
+ end
34
+
35
+ def optional
36
+ self.class.new(type: AST::Types::Union.build(types: [type, AST::Builtin.nil_type]),
37
+ annotations: annotations,
38
+ nodes: nodes)
39
+ end
40
+ end
41
+
42
+ attr_reader :declared_types
43
+ attr_reader :assigned_types
44
+
45
+ def self.empty(subtyping:, self_type:)
46
+ new(subtyping: subtyping, declared_types: {}, assigned_types: {}, self_type: self_type)
47
+ end
48
+
49
+ def initialize(subtyping:, declared_types:, assigned_types:, self_type:)
50
+ @subtyping = subtyping
51
+ @self_type = self_type
52
+
53
+ @declared_types = declared_types
54
+ @assigned_types = assigned_types
55
+
56
+ unless (intersection = Set.new(declared_types.keys) & Set.new(assigned_types.keys)).empty?
57
+ raise "Declared types and assigned types should be disjoint: #{intersection}"
58
+ end
59
+ end
60
+
61
+ def update(declared_types: self.declared_types, assigned_types: self.assigned_types, self_type: self.self_type)
62
+ self.class.new(
63
+ subtyping: subtyping,
64
+ declared_types: declared_types,
65
+ assigned_types: assigned_types,
66
+ self_type: self_type
67
+ )
68
+ end
69
+
70
+ def assign!(var, node:, type:)
71
+ declared_type = declared_types[var]&.type
72
+
73
+ if declared_type
74
+ relation = Subtyping::Relation.new(sub_type: type, super_type: declared_type)
75
+ constraints = Subtyping::Constraints.new(unknowns: Set.new)
76
+ subtyping.check(relation, constraints: constraints, self_type: self_type).else do |result|
77
+ yield declared_type, type, result
78
+ end
79
+ end
80
+
81
+ assignments = { var => Entry.new(type: type, nodes: [node]) }
82
+ update(assigned_types: assigned_types.merge(assignments),
83
+ declared_types: declared_types.reject {|k, _| k == var })
84
+ end
85
+
86
+ def assign(var, node:, type:)
87
+ declared_type = declared_types[var]&.type
88
+
89
+ if declared_type
90
+ relation = Subtyping::Relation.new(sub_type: type, super_type: declared_type)
91
+ constraints = Subtyping::Constraints.new(unknowns: Set.new)
92
+ subtyping.check(relation, constraints: constraints, self_type: self_type).else do |result|
93
+ yield declared_type, type, result
94
+ end
95
+
96
+ self
97
+ else
98
+ assignments = { var => Entry.new(type: type, nodes: [node]) }
99
+ update(assigned_types: assigned_types.merge(assignments))
100
+ end
101
+ end
102
+
103
+ def annotate(collection)
104
+ decls = collection.var_type_annotations.each.with_object({}) do |(var, annotation), hash|
105
+ type = collection.var_type(lvar: var)
106
+ hash[var] = Entry.new(type: type, annotations: [annotation])
107
+ end
108
+
109
+ decls.each do |var, annot|
110
+ inner_type = annot.type
111
+ outer_type = self[var]
112
+
113
+ if outer_type
114
+ relation = Subtyping::Relation.new(sub_type: inner_type, super_type: outer_type)
115
+ constraints = Subtyping::Constraints.new(unknowns: Set.new)
116
+ subtyping.check(relation, constraints: constraints, self_type: self_type).else do |result|
117
+ yield var, outer_type, inner_type, result
118
+ end
119
+ end
120
+ end
121
+
122
+ new_decls = declared_types.merge(decls)
123
+ new_assigns = assigned_types.reject {|var, _| new_decls.key?(var) }
124
+
125
+ update(declared_types: new_decls, assigned_types: new_assigns)
126
+ end
127
+
128
+ def [](var)
129
+ entry(var)&.type
130
+ end
131
+
132
+ def entry(var)
133
+ declared_types[var] || assigned_types[var]
134
+ end
135
+
136
+ def pin_assignments
137
+ update(
138
+ declared_types: assigned_types.merge(declared_types),
139
+ assigned_types: {}
140
+ )
141
+ end
142
+
143
+ def except(variables)
144
+ update(
145
+ declared_types: declared_types.reject {|var, _| variables.include?(var) },
146
+ assigned_types: assigned_types.reject {|var, _| variables.include?(var) }
147
+ )
148
+ end
149
+
150
+ def each
151
+ if block_given?
152
+ vars.each do |var|
153
+ yield var, self[var]
154
+ end
155
+ else
156
+ enum_for :each
157
+ end
158
+ end
159
+
160
+ def vars
161
+ @vars ||= Set.new(declared_types.keys + assigned_types.keys)
162
+ end
163
+
164
+ def join(*envs)
165
+ if envs.empty?
166
+ self
167
+ else
168
+ env = envs.inject do |env1, env2|
169
+ assigned_types = {}
170
+ declared_types = {}
171
+
172
+ (env1.vars + env2.vars).each do |var|
173
+ e1 = env1.entry(var)
174
+ e2 = env2.entry(var)
175
+ je = join_entry(e1, e2)
176
+
177
+ if env1.declared_types.key?(var) || env2.declared_types.key?(var)
178
+ declared_types[var] = je
179
+ else
180
+ assigned_types[var] = je
181
+ end
182
+ end
183
+
184
+ LocalVariableTypeEnv.new(
185
+ subtyping: subtyping,
186
+ self_type: self_type,
187
+ declared_types: declared_types,
188
+ assigned_types: assigned_types
189
+ )
190
+ end
191
+
192
+ decls = env.declared_types.merge(declared_types)
193
+ assignments = env.assigned_types.reject {|var, _| decls.key?(var) }
194
+
195
+ update(
196
+ declared_types: decls,
197
+ assigned_types: assignments,
198
+ )
199
+ end
200
+ end
201
+
202
+ def join_entry(e1, e2)
203
+ case
204
+ when e1 && e2
205
+ e1 + e2
206
+ when e1
207
+ e1.optional
208
+ when e2
209
+ e2.optional
210
+ else
211
+ raise
212
+ end
213
+ end
214
+
215
+ def to_s
216
+ ss = []
217
+
218
+ vars.each do |var|
219
+ ss << "#{var}: #{self[var].to_s}"
220
+ end
221
+
222
+ "{#{ss.join(", ")}}"
223
+ end
224
+ end
225
+ end
226
+ end
@@ -0,0 +1,130 @@
1
+ module Steep
2
+ module TypeInference
3
+ class Logic
4
+ class Result
5
+ attr_reader :nodes
6
+
7
+ def initialize(nodes = [])
8
+ @nodes = Set[].compare_by_identity.merge(nodes)
9
+ end
10
+
11
+ def +(other)
12
+ Result.new(nodes + other.nodes)
13
+ end
14
+
15
+ def merge(nodes)
16
+ Result.new(self.nodes + nodes)
17
+ end
18
+
19
+ def vars
20
+ vars = Set[]
21
+
22
+ nodes.each do |node|
23
+ case node.type
24
+ when :lvar, :lvasgn
25
+ vars << node.children[0].name
26
+ end
27
+ end
28
+
29
+ vars
30
+ end
31
+ end
32
+
33
+ attr_reader :subtyping
34
+
35
+ def initialize(subtyping:)
36
+ @subtyping = subtyping
37
+ end
38
+
39
+ def nodes(node:)
40
+ case node.type
41
+ when :lvasgn
42
+ rhs = node.children[1]
43
+ t, f = nodes(node: rhs)
44
+
45
+ [
46
+ t.merge([node]),
47
+ f.merge([node])
48
+ ]
49
+
50
+ when :and
51
+ lhs, rhs = node.children
52
+
53
+ lt, _ = nodes(node: lhs)
54
+ rt, _ = nodes(node: rhs)
55
+
56
+ [
57
+ Result.new([node]) + lt + rt,
58
+ Result.new([node])
59
+ ]
60
+
61
+ when :or
62
+ lhs, rhs = node.children
63
+
64
+ _, lf = nodes(node: lhs)
65
+ _, rf = nodes(node: rhs)
66
+
67
+ [
68
+ Result.new([node]),
69
+ Result.new([node]) + lf + rf
70
+ ]
71
+
72
+ when :begin
73
+ nodes(node: node.children.last)
74
+
75
+ else
76
+ [
77
+ Result.new([node]),
78
+ Result.new([node])
79
+ ]
80
+ end
81
+ end
82
+
83
+ def environments(truthy_vars:, falsey_vars:, lvar_env:)
84
+ truthy_hash = lvar_env.assigned_types.dup
85
+ falsey_hash = lvar_env.assigned_types.dup
86
+
87
+ (truthy_vars + falsey_vars).each do |var|
88
+ type = lvar_env[var]
89
+ truthy_type, falsey_type = partition_union(type)
90
+
91
+ if truthy_vars.include?(var)
92
+ truthy_hash[var] = LocalVariableTypeEnv::Entry.new(type: truthy_type)
93
+ end
94
+
95
+ if falsey_vars.include?(var)
96
+ falsey_hash[var] = LocalVariableTypeEnv::Entry.new(type: falsey_type)
97
+ end
98
+ end
99
+
100
+ [
101
+ lvar_env.except(truthy_vars).update(assigned_types: truthy_hash),
102
+ lvar_env.except(falsey_vars).update(assigned_types: falsey_hash)
103
+ ]
104
+ end
105
+
106
+ def partition_union(type)
107
+ case type
108
+ when AST::Types::Union
109
+ falsey_types, truthy_types = type.types.partition do |type|
110
+ case type
111
+ when AST::Types::Nil
112
+ true
113
+ when AST::Types::Literal
114
+ type.value == false
115
+ end
116
+ end
117
+
118
+ [
119
+ truthy_types.empty? ? AST::Types::Bot.new : AST::Types::Union.build(types: truthy_types),
120
+ falsey_types.empty? ? AST::Types::Bot.new : AST::Types::Union.build(types: falsey_types)
121
+ ]
122
+ when AST::Types::Any, AST::Types::Top, AST::Types::Boolean, AST::Types::Void
123
+ [type, type]
124
+ else
125
+ [type, AST::Types::Bot.new]
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end