Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4a6fc77

Browse files
committed
WithEnvironment -> WithScope
1 parent 174cc6b commit 4a6fc77

File tree

4 files changed

+67
-76
lines changed

4 files changed

+67
-76
lines changed

README.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ It is built with only standard library dependencies. It additionally ships with
4343
- [visit_methods](#visit_methods)
4444
- [BasicVisitor](#basicvisitor)
4545
- [MutationVisitor](#mutationvisitor)
46-
- [WithEnvironment](#withenvironment)
46+
- [WithScope](#withscope)
4747
- [Language server](#language-server)
4848
- [textDocument/formatting](#textdocumentformatting)
4949
- [textDocument/inlayHint](#textdocumentinlayhint)
@@ -588,20 +588,18 @@ SyntaxTree::Formatter.format(source, program.accept(visitor))
588588
# => "if (a = 1)\nend\n"
589589
```
590590

591-
### WithEnvironment
591+
### WithScope
592592

593-
The `WithEnvironment` module can be included in visitors to automatically keep track of local variables and arguments
594-
defined inside each environment. A `current_environment` accessor is made available to the request, allowing it to find
595-
all usages and definitions of a local.
593+
The `WithScope` module can be included in visitors to automatically keep track of local variables and arguments defined inside each scope. A `current_scope` accessor is made available to the request, allowing it to find all usages and definitions of a local.
596594

597595
```ruby
598596
class MyVisitor < Visitor
599-
include WithEnvironment
597+
prepend WithScope
600598

601599
def visit_ident(node)
602600
# find_local will return a Local for any local variables or arguments
603601
# present in the current environment or nil if the identifier is not a local
604-
local = current_environment.find_local(node)
602+
local = current_scope.find_local(node)
605603

606604
puts local.type # the type of the local (:variable or :argument)
607605
puts local.definitions # the array of locations where this local is defined

lib/syntax_tree.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ module SyntaxTree
3333
autoload :PrettyPrintVisitor, "syntax_tree/pretty_print_visitor"
3434
autoload :Search, "syntax_tree/search"
3535
autoload :Translation, "syntax_tree/translation"
36-
autoload :WithEnvironment, "syntax_tree/with_environment"
36+
autoload :WithScope, "syntax_tree/with_scope"
3737
autoload :YARV, "syntax_tree/yarv"
3838

3939
# This holds references to objects that respond to both #parse and #format

lib/syntax_tree/with_environment.rb renamed to lib/syntax_tree/with_scope.rb

Lines changed: 50 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
# frozen_string_literal: true
22

33
module SyntaxTree
4-
# WithEnvironment is a module intended to be included in classes inheriting
5-
# from Visitor. The module overrides a few visit methods to automatically keep
6-
# track of local variables and arguments defined in the current environment.
4+
# WithScope is a module intended to be included in classes inheriting from
5+
# Visitor. The module overrides a few visit methods to automatically keep
6+
# track of local variables and arguments defined in the current scope.
77
# Example usage:
88
#
99
# class MyVisitor < Visitor
10-
# include WithEnvironment
10+
# include WithScope
1111
#
1212
# def visit_ident(node)
1313
# # Check if we're visiting an identifier for an argument, a local
1414
# # variable or something else
15-
# local = current_environment.find_local(node)
15+
# local = current_scope.find_local(node)
1616
#
1717
# if local.type == :argument
1818
# # handle identifiers for arguments
@@ -24,11 +24,11 @@ module SyntaxTree
2424
# end
2525
# end
2626
#
27-
module WithEnvironment
28-
# The environment class is used to keep track of local variables and
29-
# arguments inside a particular scope
30-
class Environment
31-
# This class tracks the occurrences of a local variable or argument
27+
module WithScope
28+
# The scope class is used to keep track of local variables and arguments
29+
# inside a particular scope.
30+
class Scope
31+
# This class tracks the occurrences of a local variable or argument.
3232
class Local
3333
# [Symbol] The type of the local (e.g. :argument, :variable)
3434
attr_reader :type
@@ -55,20 +55,20 @@ def add_usage(location)
5555
end
5656
end
5757

58-
# [Integer] a unique identifier for this environment
58+
# [Integer] a unique identifier for this scope
5959
attr_reader :id
6060

61+
# [scope | nil] The parent scope
62+
attr_reader :parent
63+
6164
# [Hash[String, Local]] The local variables and arguments defined in this
62-
# environment
65+
# scope
6366
attr_reader :locals
6467

65-
# [Environment | nil] The parent environment
66-
attr_reader :parent
67-
6868
def initialize(id, parent = nil)
6969
@id = id
70-
@locals = {}
7170
@parent = parent
71+
@locals = {}
7272
end
7373

7474
# Adding a local definition will either insert a new entry in the locals
@@ -97,7 +97,7 @@ def add_local_usage(identifier, type)
9797
resolve_local(name, type).add_usage(identifier.location)
9898
end
9999

100-
# Try to find the local given its name in this environment or any of its
100+
# Try to find the local given its name in this scope or any of its
101101
# parents.
102102
def find_local(name)
103103
locals[name] || parent&.find_local(name)
@@ -117,44 +117,35 @@ def resolve_local(name, type)
117117
end
118118
end
119119

120+
attr_reader :current_scope
121+
120122
def initialize(*args, **kwargs, &block)
121123
super
122-
@environment_id = 0
123-
end
124-
125-
def current_environment
126-
@current_environment ||= Environment.new(next_environment_id)
127-
end
128124

129-
def with_new_environment(parent_environment = nil)
130-
previous_environment = @current_environment
131-
@current_environment =
132-
Environment.new(next_environment_id, parent_environment)
133-
yield
134-
ensure
135-
@current_environment = previous_environment
125+
@current_scope = Scope.new(0)
126+
@next_scope_id = 0
136127
end
137128

138-
# Visits for nodes that create new environments, such as classes, modules
129+
# Visits for nodes that create new scopes, such as classes, modules
139130
# and method definitions.
140131
def visit_class(node)
141-
with_new_environment { super }
132+
with_scope { super }
142133
end
143134

144135
def visit_module(node)
145-
with_new_environment { super }
136+
with_scope { super }
146137
end
147138

148-
# When we find a method invocation with a block, only the code that
149-
# happens inside of the block needs a fresh environment. The method
150-
# invocation itself happens in the same environment.
139+
# When we find a method invocation with a block, only the code that happens
140+
# inside of the block needs a fresh scope. The method invocation
141+
# itself happens in the same scope.
151142
def visit_method_add_block(node)
152143
visit(node.call)
153-
with_new_environment(current_environment) { visit(node.block) }
144+
with_scope(current_scope) { visit(node.block) }
154145
end
155146

156147
def visit_def(node)
157-
with_new_environment { super }
148+
with_scope { super }
158149
end
159150

160151
# Visit for keeping track of local arguments, such as method and block
@@ -163,48 +154,45 @@ def visit_params(node)
163154
add_argument_definitions(node.requireds)
164155

165156
node.posts.each do |param|
166-
current_environment.add_local_definition(param, :argument)
157+
current_scope.add_local_definition(param, :argument)
167158
end
168159

169160
node.keywords.each do |param|
170-
current_environment.add_local_definition(param.first, :argument)
161+
current_scope.add_local_definition(param.first, :argument)
171162
end
172163

173164
node.optionals.each do |param|
174-
current_environment.add_local_definition(param.first, :argument)
165+
current_scope.add_local_definition(param.first, :argument)
175166
end
176167

177168
super
178169
end
179170

180171
def visit_rest_param(node)
181172
name = node.name
182-
current_environment.add_local_definition(name, :argument) if name
173+
current_scope.add_local_definition(name, :argument) if name
183174

184175
super
185176
end
186177

187178
def visit_kwrest_param(node)
188179
name = node.name
189-
current_environment.add_local_definition(name, :argument) if name
180+
current_scope.add_local_definition(name, :argument) if name
190181

191182
super
192183
end
193184

194185
def visit_blockarg(node)
195186
name = node.name
196-
current_environment.add_local_definition(name, :argument) if name
187+
current_scope.add_local_definition(name, :argument) if name
197188

198189
super
199190
end
200191

201192
# Visit for keeping track of local variable definitions
202193
def visit_var_field(node)
203194
value = node.value
204-
205-
if value.is_a?(SyntaxTree::Ident)
206-
current_environment.add_local_definition(value, :variable)
207-
end
195+
current_scope.add_local_definition(value, :variable) if value.is_a?(Ident)
208196

209197
super
210198
end
@@ -215,12 +203,9 @@ def visit_var_field(node)
215203
def visit_var_ref(node)
216204
value = node.value
217205

218-
if value.is_a?(SyntaxTree::Ident)
219-
definition = current_environment.find_local(value.value)
220-
221-
if definition
222-
current_environment.add_local_usage(value, definition.type)
223-
end
206+
if value.is_a?(Ident)
207+
definition = current_scope.find_local(value.value)
208+
current_scope.add_local_usage(value, definition.type) if definition
224209
end
225210

226211
super
@@ -233,13 +218,21 @@ def add_argument_definitions(list)
233218
if param.is_a?(SyntaxTree::MLHSParen)
234219
add_argument_definitions(param.contents.parts)
235220
else
236-
current_environment.add_local_definition(param, :argument)
221+
current_scope.add_local_definition(param, :argument)
237222
end
238223
end
239224
end
240225

241-
def next_environment_id
242-
@environment_id += 1
226+
def next_scope_id
227+
@next_scope_id += 1
228+
end
229+
230+
def with_scope(parent_scope = nil)
231+
previous_scope = @current_scope
232+
@current_scope = Scope.new(next_scope_id, parent_scope)
233+
yield
234+
ensure
235+
@current_scope = previous_scope
243236
end
244237
end
245238
end

test/with_environment_test.rb renamed to test/with_scope_test.rb

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
require_relative "test_helper"
44

55
module SyntaxTree
6-
class WithEnvironmentTest < Minitest::Test
6+
class WithScopeTest < Minitest::Test
77
class Collector < Visitor
8-
prepend WithEnvironment
8+
prepend WithScope
99

1010
attr_reader :arguments, :variables
1111

@@ -21,22 +21,22 @@ def self.collect(source)
2121
visit_methods do
2222
def visit_ident(node)
2323
value = node.value.delete_suffix(":")
24-
local = current_environment.find_local(node.value)
24+
local = current_scope.find_local(node.value)
2525

2626
case local&.type
2727
when :argument
28-
arguments[[current_environment.id, value]] = local
28+
arguments[[current_scope.id, value]] = local
2929
when :variable
30-
variables[[current_environment.id, value]] = local
30+
variables[[current_scope.id, value]] = local
3131
end
3232
end
3333

3434
def visit_label(node)
3535
value = node.value.delete_suffix(":")
36-
local = current_environment.find_local(value)
36+
local = current_scope.find_local(value)
3737

3838
if local&.type == :argument
39-
arguments[[current_environment.id, value]] = node
39+
arguments[[current_scope.id, value]] = node
4040
end
4141
end
4242
end
@@ -350,7 +350,7 @@ def test_double_nested_arguments
350350
end
351351

352352
class Resolver < Visitor
353-
prepend WithEnvironment
353+
prepend WithScope
354354

355355
attr_reader :locals
356356

@@ -364,10 +364,10 @@ def visit_assign(node)
364364
level = 0
365365
name = node.target.value.value
366366

367-
environment = current_environment
368-
while !environment.locals.key?(name) && !environment.parent.nil?
367+
scope = current_scope
368+
while !scope.locals.key?(name) && !scope.parent.nil?
369369
level += 1
370-
environment = environment.parent
370+
scope = scope.parent
371371
end
372372

373373
locals << [name, level]

0 commit comments

Comments
 (0)