diff --git a/lib/typeprof/core/graph/change_set.rb b/lib/typeprof/core/graph/change_set.rb index 57bada27..44f2b54a 100644 --- a/lib/typeprof/core/graph/change_set.rb +++ b/lib/typeprof/core/graph/change_set.rb @@ -3,13 +3,6 @@ class ChangeSet def initialize(node, target) @node = node @target = target - @new_vertexes = {} - @covariant_types = {} - @contravariant_types = {} - @edges = {} - @new_edges = {} - @boxes = {} - @new_boxes = {} @diagnostics = [] @new_diagnostics = [] if target @@ -24,11 +17,19 @@ def initialize(node, target) end end - attr_reader :node, :target, :covariant_types, :contravariant_types, :edges, :boxes, :diagnostics + attr_reader :node, :target, :diagnostics + + def covariant_types = @covariant_types ||= {} + def contravariant_types = @contravariant_types ||= {} + def edges = @edges ||= {} + def boxes = @boxes ||= {} + + private def new_edges = @new_edges ||= {} + private def new_boxes = @new_boxes ||= {} def reuse(new_node) @node = new_node - @boxes.each_value do |box| + boxes.each_value do |box| box.reuse(new_node) end end @@ -48,6 +49,7 @@ def copy_from(other) end def new_vertex(genv, origin, base_vtx) + @new_vertexes ||= {} new_vtx = @new_vertexes[base_vtx] ||= Vertex.new(origin) add_edge(genv, base_vtx, new_vtx) new_vtx @@ -55,88 +57,88 @@ def new_vertex(genv, origin, base_vtx) def new_covariant_vertex(genv, sig_type_node) # This is used to avoid duplicated vertex generation for the same sig node - @covariant_types[sig_type_node] ||= Vertex.new(sig_type_node) + covariant_types[sig_type_node] ||= Vertex.new(sig_type_node) end def new_contravariant_vertex(genv, sig_type_node) # This is used to avoid duplicated vertex generation for the same sig node - @contravariant_types[sig_type_node] ||= Vertex.new(sig_type_node) + contravariant_types[sig_type_node] ||= Vertex.new(sig_type_node) end def add_edge(genv, src, dst) - (@new_edges[src] ||= {})[dst] = true + (new_edges[src] ||= {})[dst] = true end # TODO: if an edge is removed during one analysis, we may need to remove sub-boxes? def add_method_call_box(genv, recv, mid, a_args, subclasses, suppress_errors: false) key = [:mcall, recv, mid, a_args, subclasses, suppress_errors] - @new_boxes[key] ||= MethodCallBox.new(@node, genv, recv, mid, a_args, subclasses, suppress_errors: suppress_errors) + new_boxes[key] ||= MethodCallBox.new(@node, genv, recv, mid, a_args, subclasses, suppress_errors: suppress_errors) end def add_escape_box(genv, a_ret) key = [:return, a_ret] - @new_boxes[key] ||= EscapeBox.new(@node, genv, a_ret) + new_boxes[key] ||= EscapeBox.new(@node, genv, a_ret) end def add_splat_box(genv, arg, idx = nil, orig = nil) key = [:splat, arg, idx, orig] - @new_boxes[key] ||= SplatBox.new(@node, genv, arg, idx, orig) + new_boxes[key] ||= SplatBox.new(@node, genv, arg, idx, orig) end def add_hash_splat_box(genv, arg, unified_key, unified_val) key = [:hash_splat, arg, unified_key, unified_val] - @new_boxes[key] ||= HashSplatBox.new(@node, genv, arg, unified_key, unified_val) + new_boxes[key] ||= HashSplatBox.new(@node, genv, arg, unified_key, unified_val) end def add_masgn_box(genv, value, lefts, rest_elem, rights) key = [:masgn, value, lefts, rest_elem, rights] - @new_boxes[key] ||= MAsgnBox.new(@node, genv, value, lefts, rest_elem, rights) + new_boxes[key] ||= MAsgnBox.new(@node, genv, value, lefts, rest_elem, rights) end def add_method_def_box(genv, cpath, singleton, mid, f_args, ret_boxes) key = [:mdef, cpath, singleton, mid, f_args, ret_boxes] - @new_boxes[key] ||= MethodDefBox.new(@node, genv, cpath, singleton, mid, f_args, ret_boxes) + new_boxes[key] ||= MethodDefBox.new(@node, genv, cpath, singleton, mid, f_args, ret_boxes) end def add_method_decl_box(genv, cpath, singleton, mid, method_types, overloading) key = [:mdecl, cpath, singleton, mid, method_types, overloading] - @new_boxes[key] ||= MethodDeclBox.new(@node, genv, cpath, singleton, mid, method_types, overloading) + new_boxes[key] ||= MethodDeclBox.new(@node, genv, cpath, singleton, mid, method_types, overloading) end def add_method_alias_box(genv, cpath, singleton, new_mid, old_mid) key = [:mdecl, cpath, singleton, new_mid, old_mid] - @new_boxes[key] ||= MethodAliasBox.new(@node, genv, cpath, singleton, new_mid, old_mid) + new_boxes[key] ||= MethodAliasBox.new(@node, genv, cpath, singleton, new_mid, old_mid) end def add_const_read_box(genv, static_ret) key = [:cread, static_ret] - @new_boxes[key] ||= ConstReadBox.new(@node, genv, static_ret) + new_boxes[key] ||= ConstReadBox.new(@node, genv, static_ret) end def add_gvar_read_box(genv, var) key = [:gvar_read, var] - @new_boxes[key] ||= GVarReadBox.new(@node, genv, var) + new_boxes[key] ||= GVarReadBox.new(@node, genv, var) end def add_ivar_read_box(genv, cpath, singleton, name) key = [:ivar_read, cpath, singleton, name] - @new_boxes[key] ||= IVarReadBox.new(@node, genv, cpath, singleton, name) + new_boxes[key] ||= IVarReadBox.new(@node, genv, cpath, singleton, name) end def add_cvar_read_box(genv, cpath, name) key = [:cvar_read, cpath, name] - @new_boxes[key] ||= CVarReadBox.new(@node, genv, cpath, name) + new_boxes[key] ||= CVarReadBox.new(@node, genv, cpath, name) end def add_type_read_box(genv, type) key = [:type_read, type] - @new_boxes[key] ||= TypeReadBox.new(@node, genv, type) + new_boxes[key] ||= TypeReadBox.new(@node, genv, type) end def add_instance_type_box(genv, singleton_ty_vtx) key = [:instance_type, singleton_ty_vtx] - @new_boxes[key] ||= InstanceTypeBox.new(@node, genv, singleton_ty_vtx) + new_boxes[key] ||= InstanceTypeBox.new(@node, genv, singleton_ty_vtx) end def add_diagnostic(meth, msg, node = @node) @@ -161,27 +163,27 @@ def add_depended_superclass(mod) def reinstall(genv) # Edges stored as nested hashes: {src => {dst => true}} - @new_edges.each do |src, new_dsts| - old_dsts = @edges[src] + new_edges.each do |src, new_dsts| + old_dsts = edges[src] new_dsts.each_key do |dst| src.add_edge(genv, dst) unless old_dsts&.key?(dst) end end - @edges.each do |src, old_dsts| - new_dsts = @new_edges[src] + edges.each do |src, old_dsts| + new_dsts = new_edges[src] old_dsts.each_key do |dst| src.remove_edge(genv, dst) unless new_dsts&.key?(dst) end end @edges, @new_edges = @new_edges, @edges - @new_edges.each_value(&:clear) - @new_edges.clear + new_edges.each_value(&:clear) + new_edges.clear - @boxes.each do |key, box| + boxes.each do |key, box| box.destroy(genv) end @boxes, @new_boxes = @new_boxes, @boxes - @new_boxes.clear + new_boxes.clear @diagnostics.each do |diag| genv.add_diagnostic_path(diag.node.lenv.path)