class ReplTypeCompletor::RootScope::Scope
Constants
- BREAK_RESULT
- NEXT_RESULT
- PATTERNMATCH_BREAK
- RETURN_RESULT
Attributes
Public Class Methods
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 111 def self.from_binding(binding, locals) = new(RootScope.new(binding, binding.receiver, locals)) def initialize(parent, table = {}, trace_ivar: true, trace_lvar: true, self_type: nil, nesting: nil) @parent = parent @level = parent.level + 1 @trace_ivar = trace_ivar @trace_lvar = trace_lvar @module_nesting = nesting ? [nesting, *parent.module_nesting] : parent.module_nesting @self_type = self_type @terminated = false @jump_branches = [] @mergeable_changes = @table = table.transform_values { [level, _1] } end def mutable? = true def terminated? @terminated end def terminate_with(type, value) return if terminated? store_jump type, value, @mergeable_changes terminate end def store_jump(type, value, changes) return if terminated? if has_own?(type) changes[type] = [level, value] @jump_branches << changes elsif @parent.mutable? @parent.store_jump(type, value, changes) end end def terminate return if terminated? @terminated = true @table = @mergeable_changes.dup end def trace?(name) return false unless @parent type = RootScope.type_by_name(name) type == :ivar ? @trace_ivar : type == :lvar ? @trace_lvar : true end def level_of(name, var_type) case var_type when :ivar return level unless @trace_ivar when :gvar return 0 end variable_level, = @table[name] variable_level || parent.level_of(name, var_type) end def get_const(nesting, path, key = nil) key ||= [nesting.__id__, path].join('::') _l, value = @table[key] value || @parent.get_const(nesting, path, key) end def get_cvar(nesting, path, name, key = nil) key ||= [name, nesting.__id__, path].join('::') _l, value = @table[key] value || @parent.get_cvar(nesting, path, name, key) end def [](name) type = RootScope.type_by_name(name) if type == :const return get_const(nil, nil, name) || Types::NIL if name.include?('::') module_nesting.each do |(nesting, path)| value = get_const nesting, [*path, name] return value if value end return Types::NIL elsif type == :cvar return get_cvar(nil, nil, nil, name) if name.include?('::') nesting, path = module_nesting.first return get_cvar(nesting, path, name) end level, value = @table[name] if level value elsif trace? name @parent[name] elsif type == :ivar self_instance_variable_get name end end def set_const(nesting, path, value) key = [nesting.__id__, path].join('::') @table[key] = [0, value] end def set_cvar(nesting, path, name, value) key = [name, nesting.__id__, path].join('::') @table[key] = [0, value] end def []=(name, value) type = RootScope.type_by_name(name) if type == :const if name.include?('::') @table[name] = [0, value] else parent_module, parent_path = module_nesting.first set_const parent_module, [*parent_path, name], value end return elsif type == :cvar if name.include?('::') @table[name] = [0, value] else parent_module, parent_path = module_nesting.first set_cvar parent_module, parent_path, name, value end return end variable_level = level_of name, type @table[name] = [variable_level, value] if variable_level end def self_type @self_type || @parent.self_type end def global_variables gvar_keys = @table.keys.select do |name| RootScope.type_by_name(name) == :gvar end gvar_keys | @parent.global_variables end def local_variables lvar_keys = @table.keys.select do |name| RootScope.type_by_name(name) == :lvar end lvar_keys |= @parent.local_variables if @trace_lvar lvar_keys end def table_constants constants = module_nesting.flat_map do |mod, path| prefix = [mod.__id__, *path].join('::') + '::' @table.keys.select { _1.start_with? prefix }.map { _1.delete_prefix(prefix).split('::').first } end.uniq constants |= @parent.table_constants if @parent.mutable? constants end def table_module_constants(mod) prefix = "#{mod.__id__}::" constants = @table.keys.select { _1.start_with? prefix }.map { _1.delete_prefix(prefix).split('::').first } constants |= @parent.table_constants if @parent.mutable? constants end def base_scope @parent.mutable? ? @parent.base_scope : @parent end def table_instance_variables ivars = @table.keys.select { RootScope.type_by_name(_1) == :ivar } ivars |= @parent.table_instance_variables if @parent.mutable? && @trace_ivar ivars end def instance_variables modules = self_type.types.grep(Types::SingletonType).map(&:module_or_class) instances = self_type.types.grep(Types::InstanceType).filter_map(&:instances).flatten(1) self_objects = modules + instances [ self_objects.flat_map { Methods::OBJECT_INSTANCE_VARIABLES_METHOD.bind_call(_1).map(&:to_s) }, table_instance_variables ].inject([], :|) end def self_instance_variable_get(name) modules = self_type.types.grep(Types::SingletonType).map(&:module_or_class) instances = self_type.types.grep(Types::InstanceType).filter_map(&:instances).flatten(1) self_objects = modules + instances types = self_objects.map do |object| value = begin Methods::OBJECT_INSTANCE_VARIABLE_GET_METHOD.bind_call(object, name) rescue NameError end Types.type_from_object value end Types::UnionType[*types] end def table_class_variables cvars = @table.keys.filter_map { _1.split('::', 2).first if RootScope.type_by_name(_1) == :cvar } cvars |= @parent.table_class_variables if @parent.mutable? cvars end def class_variables cvars = table_class_variables m, = module_nesting.first cvars |= m.class_variables.map(&:to_s) if m.is_a? Module cvars end def constants module_nesting.flat_map do |nest,| nest.constants end.map(&:to_s) | table_constants end def merge_jumps if terminated? @terminated = false @table = @mergeable_changes merge @jump_branches @terminated = true else merge [*@jump_branches, {}] end end def conditional(&block) run_branches(block, ->(_s) {}).first || Types::NIL end def never(&block) block.call Scope.new(self, { BREAK_RESULT => nil, NEXT_RESULT => nil, PATTERNMATCH_BREAK => nil, RETURN_RESULT => nil }) end def run_branches(*blocks) results = [] branches = [] blocks.each do |block| scope = Scope.new self result = block.call scope next if scope.terminated? results << result branches << scope.mergeable_changes end terminate if branches.empty? merge branches results end def has_own?(name) @table.key? name end def update(child_scope) current_level = level child_scope.mergeable_changes.each do |name, (level, value)| self[name] = value if level <= current_level end end protected def merge(branches) current_level = level merge = {} branches.each do |changes| changes.each do |name, (level, value)| next if current_level < level (merge[name] ||= []) << value end end merge.each do |name, values| values << self[name] unless values.size == branches.size values.compact! self[name] = Types::UnionType[*values.compact] unless values.empty? end end end end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 113 def initialize(parent, table = {}, trace_ivar: true, trace_lvar: true, self_type: nil, nesting: nil) @parent = parent @level = parent.level + 1 @trace_ivar = trace_ivar @trace_lvar = trace_lvar @module_nesting = nesting ? [nesting, *parent.module_nesting] : parent.module_nesting @self_type = self_type @terminated = false @jump_branches = [] @mergeable_changes = @table = table.transform_values { [level, _1] } end
Public Instance Methods
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 182 def [](name) type = RootScope.type_by_name(name) if type == :const return get_const(nil, nil, name) || Types::NIL if name.include?('::') module_nesting.each do |(nesting, path)| value = get_const nesting, [*path, name] return value if value end return Types::NIL elsif type == :cvar return get_cvar(nil, nil, nil, name) if name.include?('::') nesting, path = module_nesting.first return get_cvar(nesting, path, name) end level, value = @table[name] if level value elsif trace? name @parent[name] elsif type == :ivar self_instance_variable_get name end end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 218 def []=(name, value) type = RootScope.type_by_name(name) if type == :const if name.include?('::') @table[name] = [0, value] else parent_module, parent_path = module_nesting.first set_const parent_module, [*parent_path, name], value end return elsif type == :cvar if name.include?('::') @table[name] = [0, value] else parent_module, parent_path = module_nesting.first set_cvar parent_module, parent_path, name, value end return end variable_level = level_of name, type @table[name] = [variable_level, value] if variable_level end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 276 def base_scope @parent.mutable? ? @parent.base_scope : @parent end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 316 def class_variables cvars = table_class_variables m, = module_nesting.first cvars |= m.class_variables.map(&:to_s) if m.is_a? Module cvars end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 340 def conditional(&block) run_branches(block, ->(_s) {}).first || Types::NIL end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 323 def constants module_nesting.flat_map do |nest,| nest.constants end.map(&:to_s) | table_constants end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 170 def get_const(nesting, path, key = nil) key ||= [nesting.__id__, path].join('::') _l, value = @table[key] value || @parent.get_const(nesting, path, key) end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 176 def get_cvar(nesting, path, name, key = nil) key ||= [name, nesting.__id__, path].join('::') _l, value = @table[key] value || @parent.get_cvar(nesting, path, name, key) end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 245 def global_variables gvar_keys = @table.keys.select do |name| RootScope.type_by_name(name) == :gvar end gvar_keys | @parent.global_variables end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 363 def has_own?(name) @table.key? name end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 286 def instance_variables modules = self_type.types.grep(Types::SingletonType).map(&:module_or_class) instances = self_type.types.grep(Types::InstanceType).filter_map(&:instances).flatten(1) self_objects = modules + instances [ self_objects.flat_map { Methods::OBJECT_INSTANCE_VARIABLES_METHOD.bind_call(_1).map(&:to_s) }, table_instance_variables ].inject([], :|) end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 159 def level_of(name, var_type) case var_type when :ivar return level unless @trace_ivar when :gvar return 0 end variable_level, = @table[name] variable_level || parent.level_of(name, var_type) end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 252 def local_variables lvar_keys = @table.keys.select do |name| RootScope.type_by_name(name) == :lvar end lvar_keys |= @parent.local_variables if @trace_lvar lvar_keys end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 376 def merge(branches) current_level = level merge = {} branches.each do |changes| changes.each do |name, (level, value)| next if current_level < level (merge[name] ||= []) << value end end merge.each do |name, values| values << self[name] unless values.size == branches.size values.compact! self[name] = Types::UnionType[*values.compact] unless values.empty? end end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 329 def merge_jumps if terminated? @terminated = false @table = @mergeable_changes merge @jump_branches @terminated = true else merge [*@jump_branches, {}] end end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 125 def mutable? = true def terminated? @terminated end def terminate_with(type, value) return if terminated? store_jump type, value, @mergeable_changes terminate end def store_jump(type, value, changes) return if terminated? if has_own?(type) changes[type] = [level, value] @jump_branches << changes elsif @parent.mutable? @parent.store_jump(type, value, changes) end end def terminate return if terminated? @terminated = true @table = @mergeable_changes.dup end def trace?(name) return false unless @parent type = RootScope.type_by_name(name) type == :ivar ? @trace_ivar : type == :lvar ? @trace_lvar : true end def level_of(name, var_type) case var_type when :ivar return level unless @trace_ivar when :gvar return 0 end variable_level, = @table[name] variable_level || parent.level_of(name, var_type) end def get_const(nesting, path, key = nil) key ||= [nesting.__id__, path].join('::') _l, value = @table[key] value || @parent.get_const(nesting, path, key) end def get_cvar(nesting, path, name, key = nil) key ||= [name, nesting.__id__, path].join('::') _l, value = @table[key] value || @parent.get_cvar(nesting, path, name, key) end def [](name) type = RootScope.type_by_name(name) if type == :const return get_const(nil, nil, name) || Types::NIL if name.include?('::') module_nesting.each do |(nesting, path)| value = get_const nesting, [*path, name] return value if value end return Types::NIL elsif type == :cvar return get_cvar(nil, nil, nil, name) if name.include?('::') nesting, path = module_nesting.first return get_cvar(nesting, path, name) end level, value = @table[name] if level value elsif trace? name @parent[name] elsif type == :ivar self_instance_variable_get name end end def set_const(nesting, path, value) key = [nesting.__id__, path].join('::') @table[key] = [0, value] end def set_cvar(nesting, path, name, value) key = [name, nesting.__id__, path].join('::') @table[key] = [0, value] end def []=(name, value) type = RootScope.type_by_name(name) if type == :const if name.include?('::') @table[name] = [0, value] else parent_module, parent_path = module_nesting.first set_const parent_module, [*parent_path, name], value end return elsif type == :cvar if name.include?('::') @table[name] = [0, value] else parent_module, parent_path = module_nesting.first set_cvar parent_module, parent_path, name, value end return end variable_level = level_of name, type @table[name] = [variable_level, value] if variable_level end def self_type @self_type || @parent.self_type end def global_variables gvar_keys = @table.keys.select do |name| RootScope.type_by_name(name) == :gvar end gvar_keys | @parent.global_variables end def local_variables lvar_keys = @table.keys.select do |name| RootScope.type_by_name(name) == :lvar end lvar_keys |= @parent.local_variables if @trace_lvar lvar_keys end def table_constants constants = module_nesting.flat_map do |mod, path| prefix = [mod.__id__, *path].join('::') + '::' @table.keys.select { _1.start_with? prefix }.map { _1.delete_prefix(prefix).split('::').first } end.uniq constants |= @parent.table_constants if @parent.mutable? constants end def table_module_constants(mod) prefix = "#{mod.__id__}::" constants = @table.keys.select { _1.start_with? prefix }.map { _1.delete_prefix(prefix).split('::').first } constants |= @parent.table_constants if @parent.mutable? constants end def base_scope @parent.mutable? ? @parent.base_scope : @parent end def table_instance_variables ivars = @table.keys.select { RootScope.type_by_name(_1) == :ivar } ivars |= @parent.table_instance_variables if @parent.mutable? && @trace_ivar ivars end def instance_variables modules = self_type.types.grep(Types::SingletonType).map(&:module_or_class) instances = self_type.types.grep(Types::InstanceType).filter_map(&:instances).flatten(1) self_objects = modules + instances [ self_objects.flat_map { Methods::OBJECT_INSTANCE_VARIABLES_METHOD.bind_call(_1).map(&:to_s) }, table_instance_variables ].inject([], :|) end def self_instance_variable_get(name) modules = self_type.types.grep(Types::SingletonType).map(&:module_or_class) instances = self_type.types.grep(Types::InstanceType).filter_map(&:instances).flatten(1) self_objects = modules + instances types = self_objects.map do |object| value = begin Methods::OBJECT_INSTANCE_VARIABLE_GET_METHOD.bind_call(object, name) rescue NameError end Types.type_from_object value end Types::UnionType[*types] end def table_class_variables cvars = @table.keys.filter_map { _1.split('::', 2).first if RootScope.type_by_name(_1) == :cvar } cvars |= @parent.table_class_variables if @parent.mutable? cvars end def class_variables cvars = table_class_variables m, = module_nesting.first cvars |= m.class_variables.map(&:to_s) if m.is_a? Module cvars end def constants module_nesting.flat_map do |nest,| nest.constants end.map(&:to_s) | table_constants end def merge_jumps if terminated? @terminated = false @table = @mergeable_changes merge @jump_branches @terminated = true else merge [*@jump_branches, {}] end end def conditional(&block) run_branches(block, ->(_s) {}).first || Types::NIL end def never(&block) block.call Scope.new(self, { BREAK_RESULT => nil, NEXT_RESULT => nil, PATTERNMATCH_BREAK => nil, RETURN_RESULT => nil }) end def run_branches(*blocks) results = [] branches = [] blocks.each do |block| scope = Scope.new self result = block.call scope next if scope.terminated? results << result branches << scope.mergeable_changes end terminate if branches.empty? merge branches results end def has_own?(name) @table.key? name end def update(child_scope) current_level = level child_scope.mergeable_changes.each do |name, (level, value)| self[name] = value if level <= current_level end end protected def merge(branches) current_level = level merge = {} branches.each do |changes| changes.each do |name, (level, value)| next if current_level < level (merge[name] ||= []) << value end end merge.each do |name, values| values << self[name] unless values.size == branches.size values.compact! self[name] = Types::UnionType[*values.compact] unless values.empty? end end end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 344 def never(&block) block.call Scope.new(self, { BREAK_RESULT => nil, NEXT_RESULT => nil, PATTERNMATCH_BREAK => nil, RETURN_RESULT => nil }) end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 348 def run_branches(*blocks) results = [] branches = [] blocks.each do |block| scope = Scope.new self result = block.call scope next if scope.terminated? results << result branches << scope.mergeable_changes end terminate if branches.empty? merge branches results end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 296 def self_instance_variable_get(name) modules = self_type.types.grep(Types::SingletonType).map(&:module_or_class) instances = self_type.types.grep(Types::InstanceType).filter_map(&:instances).flatten(1) self_objects = modules + instances types = self_objects.map do |object| value = begin Methods::OBJECT_INSTANCE_VARIABLE_GET_METHOD.bind_call(object, name) rescue NameError end Types.type_from_object value end Types::UnionType[*types] end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 241 def self_type @self_type || @parent.self_type end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 208 def set_const(nesting, path, value) key = [nesting.__id__, path].join('::') @table[key] = [0, value] end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 213 def set_cvar(nesting, path, name, value) key = [name, nesting.__id__, path].join('::') @table[key] = [0, value] end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 137 def store_jump(type, value, changes) return if terminated? if has_own?(type) changes[type] = [level, value] @jump_branches << changes elsif @parent.mutable? @parent.store_jump(type, value, changes) end end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 310 def table_class_variables cvars = @table.keys.filter_map { _1.split('::', 2).first if RootScope.type_by_name(_1) == :cvar } cvars |= @parent.table_class_variables if @parent.mutable? cvars end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 260 def table_constants constants = module_nesting.flat_map do |mod, path| prefix = [mod.__id__, *path].join('::') + '::' @table.keys.select { _1.start_with? prefix }.map { _1.delete_prefix(prefix).split('::').first } end.uniq constants |= @parent.table_constants if @parent.mutable? constants end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 280 def table_instance_variables ivars = @table.keys.select { RootScope.type_by_name(_1) == :ivar } ivars |= @parent.table_instance_variables if @parent.mutable? && @trace_ivar ivars end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 269 def table_module_constants(mod) prefix = "#{mod.__id__}::" constants = @table.keys.select { _1.start_with? prefix }.map { _1.delete_prefix(prefix).split('::').first } constants |= @parent.table_constants if @parent.mutable? constants end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 147 def terminate return if terminated? @terminated = true @table = @mergeable_changes.dup end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 131 def terminate_with(type, value) return if terminated? store_jump type, value, @mergeable_changes terminate end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 127 def terminated? @terminated end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 153 def trace?(name) return false unless @parent type = RootScope.type_by_name(name) type == :ivar ? @trace_ivar : type == :lvar ? @trace_lvar : true end
Source
# File bundled-src/repl_type_completor-0.1.12/lib/repl_type_completor/scope.rb, line 367 def update(child_scope) current_level = level child_scope.mergeable_changes.each do |name, (level, value)| self[name] = value if level <= current_level end end