Class: ReplTypeCompletor::Scope
- Inherits:
-
Object
- Object
- ReplTypeCompletor::Scope
- Defined in:
- lib/repl_type_completor/scope.rb
Constant Summary collapse
- BREAK_RESULT =
'%break'
- NEXT_RESULT =
'%next'
- RETURN_RESULT =
'%return'
- PATTERNMATCH_BREAK =
'%match'
Instance Attribute Summary collapse
-
#level ⇒ Object
readonly
Returns the value of attribute level.
-
#mergeable_changes ⇒ Object
readonly
Returns the value of attribute mergeable_changes.
-
#module_nesting ⇒ Object
readonly
Returns the value of attribute module_nesting.
-
#parent ⇒ Object
readonly
Returns the value of attribute parent.
Class Method Summary collapse
Instance Method Summary collapse
- #[](name) ⇒ Object
- #[]=(name, value) ⇒ Object
- #base_scope ⇒ Object
- #class_variables ⇒ Object
- #conditional(&block) ⇒ Object
- #constants ⇒ Object
- #get_const(nesting, path, key = nil) ⇒ Object
- #get_cvar(nesting, path, name, key = nil) ⇒ Object
- #global_variables ⇒ Object
- #has_own?(name) ⇒ Boolean
-
#initialize(parent, table = {}, trace_ivar: true, trace_lvar: true, self_type: nil, nesting: nil) ⇒ Scope
constructor
A new instance of Scope.
- #instance_variables ⇒ Object
- #level_of(name, var_type) ⇒ Object
- #local_variables ⇒ Object
- #merge_jumps ⇒ Object
- #mutable? ⇒ Boolean
- #never(&block) ⇒ Object
- #run_branches(*blocks) ⇒ Object
- #self_instance_variable_get(name) ⇒ Object
- #self_type ⇒ Object
- #set_const(nesting, path, value) ⇒ Object
- #set_cvar(nesting, path, name, value) ⇒ Object
- #store_jump(type, value, changes) ⇒ Object
- #table_class_variables ⇒ Object
- #table_constants ⇒ Object
- #table_instance_variables ⇒ Object
- #table_module_constants(mod) ⇒ Object
- #terminate ⇒ Object
- #terminate_with(type, value) ⇒ Object
- #terminated? ⇒ Boolean
- #trace?(name) ⇒ Boolean
- #update(child_scope) ⇒ Object
Constructor Details
#initialize(parent, table = {}, trace_ivar: true, trace_lvar: true, self_type: nil, nesting: nil) ⇒ Scope
Returns a new instance of Scope.
113 114 115 116 117 118 119 120 121 122 123 |
# File '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 |
Instance Attribute Details
#level ⇒ Object (readonly)
Returns the value of attribute level.
109 110 111 |
# File 'lib/repl_type_completor/scope.rb', line 109 def level @level end |
#mergeable_changes ⇒ Object (readonly)
Returns the value of attribute mergeable_changes.
109 110 111 |
# File 'lib/repl_type_completor/scope.rb', line 109 def mergeable_changes @mergeable_changes end |
#module_nesting ⇒ Object (readonly)
Returns the value of attribute module_nesting.
109 110 111 |
# File 'lib/repl_type_completor/scope.rb', line 109 def module_nesting @module_nesting end |
#parent ⇒ Object (readonly)
Returns the value of attribute parent.
109 110 111 |
# File 'lib/repl_type_completor/scope.rb', line 109 def parent @parent end |
Class Method Details
Instance Method Details
#[](name) ⇒ Object
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File '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 |
#[]=(name, value) ⇒ Object
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File '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 |
#base_scope ⇒ Object
276 277 278 |
# File 'lib/repl_type_completor/scope.rb', line 276 def base_scope @parent.mutable? ? @parent.base_scope : @parent end |
#class_variables ⇒ Object
316 317 318 319 320 321 |
# File '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 |
#conditional(&block) ⇒ Object
340 341 342 |
# File 'lib/repl_type_completor/scope.rb', line 340 def conditional(&block) run_branches(block, ->(_s) {}).first || Types::NIL end |
#constants ⇒ Object
323 324 325 326 327 |
# File '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 |
#get_const(nesting, path, key = nil) ⇒ Object
170 171 172 173 174 |
# File '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 |
#get_cvar(nesting, path, name, key = nil) ⇒ Object
176 177 178 179 180 |
# File '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 |
#global_variables ⇒ Object
245 246 247 248 249 250 |
# File '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 |
#has_own?(name) ⇒ Boolean
363 364 365 |
# File 'lib/repl_type_completor/scope.rb', line 363 def has_own?(name) @table.key? name end |
#instance_variables ⇒ Object
286 287 288 289 290 291 292 293 294 |
# File '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 |
#level_of(name, var_type) ⇒ Object
159 160 161 162 163 164 165 166 167 168 |
# File '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 |
#local_variables ⇒ Object
252 253 254 255 256 257 258 |
# File '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 |
#merge_jumps ⇒ Object
329 330 331 332 333 334 335 336 337 338 |
# File '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 |
#mutable? ⇒ Boolean
125 |
# File 'lib/repl_type_completor/scope.rb', line 125 def mutable? = true |
#never(&block) ⇒ Object
344 345 346 |
# File '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 |
#run_branches(*blocks) ⇒ Object
348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
# File '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 |
#self_instance_variable_get(name) ⇒ Object
296 297 298 299 300 301 302 303 304 305 306 307 308 |
# File '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 |
#self_type ⇒ Object
241 242 243 |
# File 'lib/repl_type_completor/scope.rb', line 241 def self_type @self_type || @parent.self_type end |
#set_const(nesting, path, value) ⇒ Object
208 209 210 211 |
# File 'lib/repl_type_completor/scope.rb', line 208 def set_const(nesting, path, value) key = [nesting.__id__, path].join('::') @table[key] = [0, value] end |
#set_cvar(nesting, path, name, value) ⇒ Object
213 214 215 216 |
# File '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 |
#store_jump(type, value, changes) ⇒ Object
137 138 139 140 141 142 143 144 145 |
# File '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 |
#table_class_variables ⇒ Object
310 311 312 313 314 |
# File '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 |
#table_constants ⇒ Object
260 261 262 263 264 265 266 267 |
# File '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 |
#table_instance_variables ⇒ Object
280 281 282 283 284 |
# File '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 |
#table_module_constants(mod) ⇒ Object
269 270 271 272 273 274 |
# File '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 |
#terminate ⇒ Object
147 148 149 150 151 |
# File 'lib/repl_type_completor/scope.rb', line 147 def terminate return if terminated? @terminated = true @table = @mergeable_changes.dup end |
#terminate_with(type, value) ⇒ Object
131 132 133 134 135 |
# File 'lib/repl_type_completor/scope.rb', line 131 def terminate_with(type, value) return if terminated? store_jump type, value, @mergeable_changes terminate end |
#terminated? ⇒ Boolean
127 128 129 |
# File 'lib/repl_type_completor/scope.rb', line 127 def terminated? @terminated end |
#trace?(name) ⇒ Boolean
153 154 155 156 157 |
# File '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 |
#update(child_scope) ⇒ Object
367 368 369 370 371 372 |
# File '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 |