Skip to content

Commit 3693091

Browse files
committed
Add Node#copy and MutationVisitor
1 parent 7710cee commit 3693091

File tree

7 files changed

+33
-0
lines changed

7 files changed

+33
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ a.out
2929
/java/org/yarp/AbstractNodeVisitor.java
3030
/java/org/yarp/Loader.java
3131
/java/org/yarp/Nodes.java
32+
/lib/yarp/mutation_visitor.rb
3233
/lib/yarp/node.rb
3334
/lib/yarp/serialize.rb
3435
/src/node.c

docs/configuration.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ A lot of code in YARP's repository is templated from a single configuration file
77
* `java/org/yarp/AbstractNodeVisitor.java` - for defining the visitor interface for the nodes in Java
88
* `java/org/yarp/Loader.java` - for defining how to deserialize the nodes in Java
99
* `java/org/yarp/Nodes.java` - for defining the nodes in Java
10+
* `lib/yarp/mutation_visitor.rb` - for defining the mutation visitor for the nodes in Ruby
1011
* `lib/yarp/node.rb` - for defining the nodes in Ruby
1112
* `lib/yarp/serialize.rb` - for defining how to deserialize the nodes in Ruby
1213
* `src/node.c` - for defining how to free the nodes in C and calculate the size in memory in C

lib/yarp.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ def self.parse_serialize_file(filepath)
507507
end
508508

509509
require_relative "yarp/lex_compat"
510+
require_relative "yarp/mutation_visitor"
510511
require_relative "yarp/node"
511512
require_relative "yarp/ripper_compat"
512513
require_relative "yarp/serialize"
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module YARP
2+
# This visitor walks through the tree and copies each node as it is being
3+
# visited. This is useful for consumers that want to mutate the tree, as you
4+
# can change subtrees in place without effecting the rest of the tree.
5+
class MutationVisitor < BasicVisitor
6+
<%- nodes.each_with_index do |node, index| -%>
7+
<%= "\n" if index != 0 -%>
8+
# Copy a <%= node.name %> node
9+
def visit_<%= node.human %>(node)
10+
<%- params = node.params.select { |param| [NodeParam, OptionalNodeParam, NodeListParam].include?(param.class) } -%>
11+
<%- if params.any? -%>
12+
node.copy(<%= params.map { |param| "#{param.name}: visit(node.#{param.name})" }.join(", ") %>)
13+
<%- else -%>
14+
node.copy
15+
<%- end -%>
16+
end
17+
<%- end -%>
18+
end
19+
end

templates/lib/yarp/node.rb.erb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,15 @@ module YARP
4848
}.compact.join(", ") %>]
4949
end
5050

51+
# def copy: (**params) -> <%= node.name %>
52+
def copy(**params)
53+
<%= node.name %>.new(
54+
<%- (node.params.map(&:name) + ["location"]).map do |name| -%>
55+
<%= name %>: params.fetch(:<%= name %>) { self.<%= name %> },
56+
<%- end -%>
57+
)
58+
end
59+
5160
# def deconstruct: () -> Array[nil | Node]
5261
alias deconstruct child_nodes
5362

templates/template.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ def locals
315315
"java/org/yarp/Loader.java",
316316
"java/org/yarp/Nodes.java",
317317
"java/org/yarp/AbstractNodeVisitor.java",
318+
"lib/yarp/mutation_visitor.rb",
318319
"lib/yarp/node.rb",
319320
"lib/yarp/serialize.rb",
320321
"src/node.c",

yarp.gemspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ Gem::Specification.new do |spec|
6161
"lib/yarp.rb",
6262
"lib/yarp/ffi.rb",
6363
"lib/yarp/lex_compat.rb",
64+
"lib/yarp/mutation_visitor.rb",
6465
"lib/yarp/node.rb",
6566
"lib/yarp/pack.rb",
6667
"lib/yarp/ripper_compat.rb",

0 commit comments

Comments
 (0)