typeprof 0.21.11 → 0.30.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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -31
  3. data/bin/typeprof +5 -0
  4. data/doc/doc.ja.md +134 -0
  5. data/doc/doc.md +136 -0
  6. data/lib/typeprof/cli/cli.rb +180 -0
  7. data/lib/typeprof/cli.rb +2 -133
  8. data/lib/typeprof/code_range.rb +112 -0
  9. data/lib/typeprof/core/ast/base.rb +263 -0
  10. data/lib/typeprof/core/ast/call.rb +251 -0
  11. data/lib/typeprof/core/ast/const.rb +126 -0
  12. data/lib/typeprof/core/ast/control.rb +432 -0
  13. data/lib/typeprof/core/ast/meta.rb +150 -0
  14. data/lib/typeprof/core/ast/method.rb +335 -0
  15. data/lib/typeprof/core/ast/misc.rb +263 -0
  16. data/lib/typeprof/core/ast/module.rb +123 -0
  17. data/lib/typeprof/core/ast/pattern.rb +140 -0
  18. data/lib/typeprof/core/ast/sig_decl.rb +471 -0
  19. data/lib/typeprof/core/ast/sig_type.rb +663 -0
  20. data/lib/typeprof/core/ast/value.rb +319 -0
  21. data/lib/typeprof/core/ast/variable.rb +315 -0
  22. data/lib/typeprof/core/ast.rb +472 -0
  23. data/lib/typeprof/core/builtin.rb +146 -0
  24. data/lib/typeprof/core/env/method.rb +137 -0
  25. data/lib/typeprof/core/env/method_entity.rb +55 -0
  26. data/lib/typeprof/core/env/module_entity.rb +408 -0
  27. data/lib/typeprof/core/env/static_read.rb +155 -0
  28. data/lib/typeprof/core/env/type_alias_entity.rb +27 -0
  29. data/lib/typeprof/core/env/value_entity.rb +32 -0
  30. data/lib/typeprof/core/env.rb +360 -0
  31. data/lib/typeprof/core/graph/box.rb +991 -0
  32. data/lib/typeprof/core/graph/change_set.rb +224 -0
  33. data/lib/typeprof/core/graph/filter.rb +155 -0
  34. data/lib/typeprof/core/graph/vertex.rb +222 -0
  35. data/lib/typeprof/core/graph.rb +3 -0
  36. data/lib/typeprof/core/service.rb +522 -0
  37. data/lib/typeprof/core/type.rb +348 -0
  38. data/lib/typeprof/core/util.rb +81 -0
  39. data/lib/typeprof/core.rb +32 -0
  40. data/lib/typeprof/diagnostic.rb +35 -0
  41. data/lib/typeprof/lsp/messages.rb +430 -0
  42. data/lib/typeprof/lsp/server.rb +177 -0
  43. data/lib/typeprof/lsp/text.rb +69 -0
  44. data/lib/typeprof/lsp/util.rb +61 -0
  45. data/lib/typeprof/lsp.rb +4 -907
  46. data/lib/typeprof/version.rb +1 -1
  47. data/lib/typeprof.rb +4 -18
  48. data/typeprof.gemspec +5 -7
  49. metadata +48 -35
  50. data/.github/dependabot.yml +0 -6
  51. data/.github/workflows/main.yml +0 -39
  52. data/.gitignore +0 -9
  53. data/Gemfile +0 -17
  54. data/Gemfile.lock +0 -41
  55. data/Rakefile +0 -10
  56. data/exe/typeprof +0 -10
  57. data/lib/typeprof/analyzer.rb +0 -2598
  58. data/lib/typeprof/arguments.rb +0 -414
  59. data/lib/typeprof/block.rb +0 -176
  60. data/lib/typeprof/builtin.rb +0 -893
  61. data/lib/typeprof/code-range.rb +0 -177
  62. data/lib/typeprof/config.rb +0 -158
  63. data/lib/typeprof/container-type.rb +0 -912
  64. data/lib/typeprof/export.rb +0 -589
  65. data/lib/typeprof/import.rb +0 -852
  66. data/lib/typeprof/insns-def.rb +0 -65
  67. data/lib/typeprof/iseq.rb +0 -864
  68. data/lib/typeprof/method.rb +0 -355
  69. data/lib/typeprof/type.rb +0 -1140
  70. data/lib/typeprof/utils.rb +0 -212
  71. data/tools/coverage.rb +0 -14
  72. data/tools/setup-insns-def.rb +0 -30
  73. data/typeprof-lsp +0 -3
@@ -0,0 +1,224 @@
1
+ module TypeProf::Core
2
+ class ChangeSet
3
+ def initialize(node, target)
4
+ @node = node
5
+ @target = target
6
+ @covariant_types = {}
7
+ @contravariant_types = {}
8
+ @edges = []
9
+ @new_edges = []
10
+ @boxes = {}
11
+ @new_boxes = {}
12
+ @diagnostics = []
13
+ @new_diagnostics = []
14
+ @depended_value_entities = []
15
+ @new_depended_value_entities = []
16
+ @depended_method_entities = []
17
+ @new_depended_method_entities = []
18
+ @depended_static_reads = []
19
+ @new_depended_static_reads = []
20
+ @depended_superclasses = []
21
+ @new_depended_superclasses = []
22
+ end
23
+
24
+ attr_reader :node, :covariant_types, :edges, :boxes, :diagnostics
25
+
26
+ def reuse(new_node)
27
+ @node = new_node
28
+ @boxes.each_value do |box|
29
+ box.reuse(new_node)
30
+ end
31
+ @diagnostics.each do |diag|
32
+ diag.reuse(new_node)
33
+ end
34
+ end
35
+
36
+ def copy_from(other)
37
+ @covariant_types = other.covariant_types.dup
38
+ @edges = other.edges.dup
39
+ @boxes = other.boxes.dup
40
+ @diagnostics = other.diagnostics.dup
41
+
42
+ other.covariant_types.clear
43
+ other.edges.clear
44
+ other.boxes.clear
45
+ other.diagnostics.clear
46
+ end
47
+
48
+ def new_covariant_vertex(genv, sig_type_node)
49
+ # This is used to avoid duplicated vertex generation for the same sig node
50
+ @covariant_types[sig_type_node] ||= Vertex.new(sig_type_node)
51
+ end
52
+
53
+ def new_contravariant_vertex(genv, sig_type_node)
54
+ # This is used to avoid duplicated vertex generation for the same sig node
55
+ @contravariant_types[sig_type_node] ||= Vertex.new(sig_type_node)
56
+ end
57
+
58
+ def add_edge(genv, src, dst)
59
+ raise src.class.to_s unless src.is_a?(BasicVertex)
60
+ src.add_edge(genv, dst) if !@edges.include?([src, dst]) && !@new_edges.include?([src, dst])
61
+ @new_edges << [src, dst]
62
+ end
63
+
64
+ # TODO: if an edge is removed during one analysis, we may need to remove sub-boxes?
65
+
66
+ def add_method_call_box(genv, recv, mid, a_args, subclasses)
67
+ key = [:mcall, recv, mid, a_args, subclasses]
68
+ return if @new_boxes[key]
69
+ @new_boxes[key] = MethodCallBox.new(@node, genv, recv, mid, a_args, subclasses)
70
+ end
71
+
72
+ def add_escape_box(genv, a_ret, f_ret)
73
+ key = [:return, a_ret]
74
+ return if @new_boxes[key]
75
+ @new_boxes[key] = EscapeBox.new(@node, genv, a_ret, f_ret)
76
+ end
77
+
78
+ def add_splat_box(genv, arg)
79
+ key = [:splat, arg]
80
+ return if @new_boxes[key]
81
+ @new_boxes[key] = SplatBox.new(@node, genv, arg)
82
+ end
83
+
84
+ def add_hash_splat_box(genv, arg, unified_key, unified_val)
85
+ key = [:hash_splat, arg, unified_key, unified_val]
86
+ return if @new_boxes[key]
87
+ @new_boxes[key] = HashSplatBox.new(@node, genv, arg, unified_key, unified_val)
88
+ end
89
+
90
+ def add_masgn_box(genv, value, lefts, rest_elem, rights)
91
+ key = [:masgn, value, lefts, rest_elem, rights]
92
+ return if @new_boxes[key]
93
+ @new_boxes[key] = MAsgnBox.new(@node, genv, value, lefts, rest_elem, rights)
94
+ end
95
+
96
+ def add_method_def_box(genv, cpath, singleton, mid, f_args, ret_boxes)
97
+ key = [:mdef, cpath, singleton, mid, f_args, ret_boxes]
98
+ return if @new_boxes[key]
99
+ @new_boxes[key] = MethodDefBox.new(@node, genv, cpath, singleton, mid, f_args, ret_boxes)
100
+ end
101
+
102
+ def add_method_decl_box(genv, cpath, singleton, mid, method_types, overloading)
103
+ key = [:mdecl, cpath, singleton, mid, method_types, overloading]
104
+ return if @new_boxes[key]
105
+ @new_boxes[key] = MethodDeclBox.new(@node, genv, cpath, singleton, mid, method_types, overloading)
106
+ end
107
+
108
+ def add_method_alias_box(genv, cpath, singleton, new_mid, old_mid)
109
+ key = [:mdecl, cpath, singleton, new_mid, old_mid]
110
+ return if @new_boxes[key]
111
+ @new_boxes[key] = MethodAliasBox.new(@node, genv, cpath, singleton, new_mid, old_mid)
112
+ end
113
+
114
+ def add_const_read_box(genv, static_ret)
115
+ key = [:cread, static_ret]
116
+ return if @new_boxes[key]
117
+ @new_boxes[key] = ConstReadBox.new(@node, genv, static_ret)
118
+ end
119
+
120
+ def add_gvar_read_box(genv, var)
121
+ key = [:gvar_read, var]
122
+ return if @new_boxes[key]
123
+ @new_boxes[key] = GVarReadBox.new(@node, genv, var)
124
+ end
125
+
126
+ def add_ivar_read_box(genv, cpath, singleton, name)
127
+ key = [:ivar_read, cpath, singleton, name]
128
+ return if @new_boxes[key]
129
+ @new_boxes[key] = IVarReadBox.new(@node, genv, cpath, singleton, name)
130
+ end
131
+
132
+ def add_cvar_read_box(genv, cpath, name)
133
+ key = [:cvar_read, cpath, name]
134
+ return if @new_boxes[key]
135
+ @new_boxes[key] = CVarReadBox.new(@node, genv, cpath, name)
136
+ end
137
+
138
+ def add_type_read_box(genv, type)
139
+ key = [:type_read, type]
140
+ return if @new_boxes[key]
141
+ @new_boxes[key] = TypeReadBox.new(@node, genv, type)
142
+ end
143
+
144
+ def add_diagnostic(meth, msg)
145
+ @new_diagnostics << TypeProf::Diagnostic.new(@node, meth, msg)
146
+ end
147
+
148
+ def add_depended_value_entity(ve)
149
+ @new_depended_value_entities << ve
150
+ end
151
+
152
+ def add_depended_method_entity(me)
153
+ @new_depended_method_entities << me
154
+ end
155
+
156
+ def add_depended_static_read(static_read)
157
+ @new_depended_static_reads << static_read
158
+ end
159
+
160
+ def add_depended_superclass(mod)
161
+ @new_depended_superclasses << mod
162
+ end
163
+
164
+ def reinstall(genv)
165
+ @new_edges.uniq!
166
+ @edges.each do |src, dst|
167
+ src.remove_edge(genv, dst) unless @new_edges.include?([src, dst])
168
+ end
169
+ @edges, @new_edges = @new_edges, @edges
170
+ @new_edges.clear
171
+
172
+ @boxes.each do |key, box|
173
+ box.destroy(genv)
174
+ end
175
+ @boxes, @new_boxes = @new_boxes, @boxes
176
+ @new_boxes.clear
177
+
178
+ @diagnostics, @new_diagnostics = @new_diagnostics, @diagnostics
179
+ @new_diagnostics.clear
180
+
181
+ @depended_value_entities.each do |ve|
182
+ ve.read_boxes.delete(@target) || raise
183
+ end
184
+ @new_depended_value_entities.uniq!
185
+ @new_depended_value_entities.each do |ve|
186
+ ve.read_boxes << @target
187
+ end
188
+ @depended_value_entities, @new_depended_value_entities = @new_depended_value_entities, @depended_value_entities
189
+ @new_depended_value_entities.clear
190
+
191
+ @depended_method_entities.each do |me|
192
+ me.method_call_boxes.delete(@target) || raise
193
+ end
194
+ @new_depended_method_entities.uniq!
195
+ @new_depended_method_entities.each do |me|
196
+ me.method_call_boxes << @target
197
+ end
198
+ @depended_method_entities, @new_depended_method_entities = @new_depended_method_entities, @depended_method_entities
199
+ @new_depended_method_entities.clear
200
+
201
+ @depended_static_reads.each do |static_read|
202
+ static_read.followers.delete(@target)
203
+ end
204
+ @new_depended_static_reads.uniq!
205
+ @new_depended_static_reads.each do |static_read|
206
+ static_read.followers << @target
207
+ end
208
+
209
+ @depended_static_reads, @new_depended_static_reads = @new_depended_static_reads, @depended_static_reads
210
+ @new_depended_static_reads.clear
211
+
212
+ @depended_superclasses.each do |mod|
213
+ mod.subclass_checks.delete(@target)
214
+ end
215
+ @new_depended_superclasses.uniq!
216
+ @new_depended_superclasses.each do |mod|
217
+ mod.subclass_checks << @target
218
+ end
219
+
220
+ @depended_superclasses, @new_depended_superclasses = @new_depended_superclasses, @depended_superclasses
221
+ @new_depended_superclasses.clear
222
+ end
223
+ end
224
+ end
@@ -0,0 +1,155 @@
1
+ module TypeProf::Core
2
+ class Filter
3
+ def destroyed
4
+ false
5
+ end
6
+ end
7
+
8
+ class NilFilter < Filter
9
+ def initialize(genv, node, prev_vtx, allow_nil)
10
+ @node = node
11
+ @next_vtx = Vertex.new(node)
12
+ @allow_nil = allow_nil
13
+ prev_vtx.add_edge(genv, self)
14
+ end
15
+
16
+ attr_reader :next_vtx, :allow_nil
17
+
18
+ def filter(types, nil_type)
19
+ types.select {|ty| (ty == nil_type) == @allow_nil }
20
+ end
21
+
22
+ def on_type_added(genv, src_var, added_types)
23
+ types = filter(added_types, genv.nil_type)
24
+ @next_vtx.on_type_added(genv, self, types) unless types.empty?
25
+ end
26
+
27
+ def on_type_removed(genv, src_var, removed_types)
28
+ types = filter(removed_types, genv.nil_type)
29
+ @next_vtx.on_type_removed(genv, self, types) unless types.empty?
30
+ end
31
+
32
+ #@@new_id = 0
33
+
34
+ def to_s
35
+ "NF#{ @id ||= $new_id += 1 } -> #{ @next_vtx }"
36
+ end
37
+ end
38
+
39
+ class IsAFilter < Filter
40
+ def initialize(genv, node, prev_vtx, neg, const_read)
41
+ @node = node
42
+ @types = Set[]
43
+ @const_read = const_read
44
+ @const_read.followers << self
45
+ @next_vtx = Vertex.new(node)
46
+ prev_vtx.add_edge(genv, self)
47
+ @neg = neg
48
+ end
49
+
50
+ attr_reader :next_vtx
51
+
52
+ def on_type_added(genv, src_var, added_types)
53
+ added_types.each do |ty|
54
+ @types << ty
55
+ end
56
+ run(genv)
57
+ end
58
+
59
+ def on_type_removed(genv, src_var, removed_types)
60
+ removed_types.each do |ty|
61
+ @types.delete(ty) || raise
62
+ end
63
+ run(genv)
64
+ end
65
+
66
+ def run(genv)
67
+ if @const_read && @const_read.cpath
68
+ passed_types = []
69
+ @types.each do |ty|
70
+ base_ty = ty.base_type(genv)
71
+ subclass = false
72
+ genv.each_superclass(base_ty.mod, base_ty.is_a?(Type::Singleton)) do |mod, singleton|
73
+ if mod.cpath == @const_read.cpath
74
+ subclass = true
75
+ break
76
+ end
77
+ end
78
+ passed_types << ty if subclass != @neg
79
+ end
80
+ else
81
+ passed_types = @types.to_a
82
+ end
83
+ added_types = passed_types - @next_vtx.types.keys
84
+ removed_types = @next_vtx.types.keys - passed_types
85
+ @next_vtx.on_type_added(genv, self, added_types)
86
+ @next_vtx.on_type_removed(genv, self, removed_types)
87
+ end
88
+
89
+ #@@new_id = 0
90
+
91
+ def to_s
92
+ "NF#{ @id ||= $new_id += 1 } -> #{ @next_vtx }"
93
+ end
94
+ end
95
+
96
+ class BotFilter < Filter
97
+ def initialize(genv, node, prev_vtx, base_vtx)
98
+ @node = node
99
+ @types = {}
100
+ @prev_vtx = prev_vtx
101
+ @next_vtx = Vertex.new(node)
102
+ @base_vtx = base_vtx
103
+ base_vtx.add_edge(genv, self)
104
+ prev_vtx.add_edge(genv, self) if prev_vtx != base_vtx
105
+ end
106
+
107
+ attr_reader :types, :prev_vtx, :next_vtx, :base_vtx
108
+
109
+ def filter(types)
110
+ types.select {|ty| (ty == genv.nil_type) == @allow_nil }
111
+ end
112
+
113
+ def on_type_added(genv, src_var, added_types)
114
+ if src_var == @base_vtx
115
+ if @base_vtx.types.size == 1 && @base_vtx.types.include?(Type::Bot.new(genv))
116
+ @next_vtx.on_type_removed(genv, self, @types.keys & @next_vtx.types.keys) # XXX: smoke/control/bot2.rb
117
+ end
118
+ else
119
+ added_types.each do |ty|
120
+ @types[ty] = true
121
+ end
122
+ if @base_vtx.types.size == 1 && @base_vtx.types.include?(Type::Bot.new(genv))
123
+ # ignore
124
+ else
125
+ @next_vtx.on_type_added(genv, self, added_types - @next_vtx.types.keys) # XXX: smoke/control/bot4.rb
126
+ end
127
+ end
128
+ end
129
+
130
+ def on_type_removed(genv, src_var, removed_types)
131
+ if src_var == @base_vtx
132
+ if @base_vtx.types.size == 1 && @base_vtx.types.include?(Type::Bot.new(genv))
133
+ # ignore
134
+ else
135
+ @next_vtx.on_type_added(genv, self, @types.keys - @next_vtx.types.keys) # XXX: smoke/control/bot4.rb
136
+ end
137
+ else
138
+ removed_types.each do |ty|
139
+ @types.delete(ty) || raise
140
+ end
141
+ if @base_vtx.types.size == 1 && @base_vtx.types.include?(Type::Bot.new(genv))
142
+ # ignore
143
+ else
144
+ @next_vtx.on_type_removed(genv, self, removed_types & @next_vtx.types.keys) # XXX: smoke/control/bot2.rb
145
+ end
146
+ end
147
+ end
148
+
149
+ #@@new_id = 0
150
+
151
+ def to_s
152
+ "BF#{ @id ||= $new_id += 1 } -> #{ @next_vtx }"
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,222 @@
1
+ module TypeProf::Core
2
+ class BasicVertex
3
+ def initialize(types)
4
+ @types = types
5
+ @types_to_be_added = {}
6
+ end
7
+
8
+ attr_reader :types
9
+
10
+ def each_type(&blk)
11
+ @types.each_key(&blk)
12
+
13
+ until @types_to_be_added.empty?
14
+ h = @types_to_be_added.dup
15
+ h.each do |ty, source|
16
+ @types[ty] = source
17
+ end
18
+ @types_to_be_added.clear
19
+ h.each_key(&blk)
20
+ end
21
+ end
22
+
23
+ def check_match(genv, changes, vtx)
24
+ vtx.each_type do |ty|
25
+ if ty.is_a?(Type::Var)
26
+ changes.add_edge(genv, self, ty.vtx) if self != ty.vtx
27
+ return true
28
+ end
29
+ end
30
+
31
+ return true if @types.empty?
32
+ return true if vtx.types.empty?
33
+
34
+ each_type do |ty|
35
+ return true if vtx.types.include?(ty) # fast path
36
+ if ty.check_match(genv, changes, vtx)
37
+ return true
38
+ end
39
+ end
40
+
41
+ return false
42
+ end
43
+
44
+ def show
45
+ if Fiber[:show_rec].include?(self)
46
+ "untyped"
47
+ else
48
+ begin
49
+ Fiber[:show_rec] << self
50
+ types = []
51
+ bot = @types.keys.any? {|ty| ty.is_a?(Type::Bot) }
52
+ optional = true_exist = false_exist = false
53
+ each_type do |ty|
54
+ if ty.is_a?(Type::Instance)
55
+ case ty.mod.cpath
56
+ when [:NilClass] then optional = true
57
+ when [:TrueClass] then true_exist = true
58
+ when [:FalseClass] then false_exist = true
59
+ end
60
+ end
61
+ end
62
+ bool = true_exist && false_exist
63
+ types << "bool" if bool
64
+ each_type do |ty, _source|
65
+ if ty.is_a?(Type::Instance)
66
+ next if ty.mod.cpath == [:NilClass]
67
+ next if bool && (ty.mod.cpath == [:TrueClass] || ty.mod.cpath == [:FalseClass])
68
+ end
69
+ next if ty.is_a?(Type::Bot)
70
+ types << ty.show
71
+ end
72
+ types = types.uniq.sort
73
+ case types.size
74
+ when 0
75
+ optional ? "nil" : bot ? "bot" : "untyped"
76
+ when 1
77
+ types.first + (optional ? "?" : "")
78
+ else
79
+ "(#{ types.join(" | ") })" + (optional ? "?" : "")
80
+ end
81
+ ensure
82
+ Fiber[:show_rec].delete(self) || raise
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ class Source < BasicVertex
89
+ def initialize(*tys)
90
+ types = {}
91
+ tys.each do |ty|
92
+ raise ty.inspect unless ty.is_a?(Type)
93
+ types[ty] = true
94
+ end
95
+ super(types)
96
+ end
97
+
98
+ def on_type_added(genv, src_var, added_types)
99
+ # TODO: need to report error?
100
+ end
101
+
102
+ def on_type_removed(genv, src_var, removed_types)
103
+ end
104
+
105
+ def new_vertex(genv, origin)
106
+ nvtx = Vertex.new(origin)
107
+ add_edge(genv, nvtx)
108
+ nvtx
109
+ end
110
+
111
+ def add_edge(genv, nvtx)
112
+ nvtx.on_type_added(genv, self, @types.keys)
113
+ end
114
+
115
+ def remove_edge(genv, nvtx)
116
+ nvtx.on_type_removed(genv, self, @types.keys)
117
+ end
118
+
119
+ def show
120
+ if Fiber[:show_rec].include?(self)
121
+ "...(recursive)..."
122
+ else
123
+ begin
124
+ Fiber[:show_rec] << self
125
+ @types.empty? ? "untyped" : @types.keys.map {|ty| ty.show }.sort.join(" | ")
126
+ ensure
127
+ Fiber[:show_rec].delete(self) || raise
128
+ end
129
+ end
130
+ end
131
+
132
+ def to_s
133
+ "<src:#{ show }>"
134
+ end
135
+
136
+ alias inspect to_s
137
+ end
138
+
139
+ class Vertex < BasicVertex
140
+ def initialize(origin)
141
+ # Note that origin is just for debug.
142
+ # When an AST node is reused, the value of the origin will be invalid.
143
+ case origin
144
+ when AST::Node
145
+ when RBS::AST::Declarations::Base
146
+ when ValueEntity
147
+ when ActualArguments
148
+ when Array
149
+ else
150
+ raise "unknown class: #{ origin.class }"
151
+ end
152
+ @next_vtxs = Set[]
153
+ super({})
154
+ end
155
+
156
+ attr_reader :next_vtxs, :types
157
+
158
+ def on_type_added(genv, src_var, added_types)
159
+ new_added_types = []
160
+ added_types.each do |ty|
161
+ if @types[ty]
162
+ @types[ty] << src_var
163
+ else
164
+ set = Set[]
165
+ begin
166
+ @types[ty] = set
167
+ rescue
168
+ @types_to_be_added[ty] = set
169
+ end
170
+ set << src_var
171
+ new_added_types << ty
172
+ end
173
+ end
174
+ unless new_added_types.empty?
175
+ @next_vtxs.each do |nvtx|
176
+ nvtx.on_type_added(genv, self, new_added_types)
177
+ end
178
+ end
179
+ end
180
+
181
+ def on_type_removed(genv, src_var, removed_types)
182
+ new_removed_types = []
183
+ removed_types.each do |ty|
184
+ raise "!!! not implemented" if @types_to_be_added[ty]
185
+ @types[ty].delete(src_var) || raise
186
+ if @types[ty].empty?
187
+ @types.delete(ty) || raise
188
+ new_removed_types << ty
189
+ end
190
+ end
191
+ unless new_removed_types.empty?
192
+ @next_vtxs.each do |nvtx|
193
+ nvtx.on_type_removed(genv, self, new_removed_types)
194
+ end
195
+ end
196
+ end
197
+
198
+ def new_vertex(genv, origin)
199
+ nvtx = Vertex.new(origin)
200
+ add_edge(genv, nvtx)
201
+ nvtx
202
+ end
203
+
204
+ def add_edge(genv, nvtx)
205
+ @next_vtxs << nvtx
206
+ nvtx.on_type_added(genv, self, @types.keys) unless @types.empty?
207
+ end
208
+
209
+ def remove_edge(genv, nvtx)
210
+ @next_vtxs.delete(nvtx) || raise
211
+ nvtx.on_type_removed(genv, self, @types.keys) unless @types.empty?
212
+ end
213
+
214
+ $new_id = 0 # TODO: Use class variable
215
+
216
+ def to_s
217
+ "v#{ @id ||= $new_id += 1 }"
218
+ end
219
+
220
+ alias inspect to_s
221
+ end
222
+ end
@@ -0,0 +1,3 @@
1
+ module TypeProf::Core
2
+ Fiber[:show_rec] = Set[]
3
+ end