diff options
author | Kevin Newton <kddnewton@gmail.com> | 2023-08-29 08:38:33 -0400 |
---|---|---|
committer | git <svn-admin@ruby-lang.org> | 2023-08-30 16:51:17 +0000 |
commit | c4998bc3f2f1978fbbe3f192f3d692523ee266d3 (patch) | |
tree | d266e1ebeaf3e29b1f792cd692b466ed0138c698 /lib | |
parent | 06f54c9a8c3058883e4c42c5b0d3c6e498d2f3ad (diff) |
[ruby/yarp] Desugar ||= more accurately
Class variables, global variables, constants, and constant paths
should actually desugar to `defined?` instead of just reading the
value.
https://github.com/ruby/yarp/commit/551a59b876
Diffstat (limited to 'lib')
-rw-r--r-- | lib/yarp/desugar_visitor.rb | 140 |
1 files changed, 70 insertions, 70 deletions
diff --git a/lib/yarp/desugar_visitor.rb b/lib/yarp/desugar_visitor.rb index 83a9bb5336..8fe488368e 100644 --- a/lib/yarp/desugar_visitor.rb +++ b/lib/yarp/desugar_visitor.rb @@ -8,26 +8,16 @@ module YARP # # @@foo && @@foo = bar def visit_class_variable_and_write_node(node) - AndNode.new( - ClassVariableReadNode.new(node.name_loc), - ClassVariableWriteNode.new(node.name_loc, node.value, node.operator_loc, node.location), - node.operator_loc, - node.location - ) + desugar_and_write_node(node, ClassVariableReadNode, ClassVariableWriteNode) end # @@foo ||= bar # # becomes # - # @@foo || @@foo = bar + # defined?(@@foo) ? @@foo : @@foo = bar def visit_class_variable_or_write_node(node) - OrNode.new( - ClassVariableReadNode.new(node.name_loc), - ClassVariableWriteNode.new(node.name_loc, node.value, node.operator_loc, node.location), - node.operator_loc, - node.location - ) + desugar_or_write_defined_node(node, ClassVariableReadNode, ClassVariableWriteNode) end # @@foo += bar @@ -36,7 +26,7 @@ module YARP # # @@foo = @@foo + bar def visit_class_variable_operator_write_node(node) - desugar_operator_write_node(node, ClassVariableWriteNode, ClassVariableReadNode) + desugar_operator_write_node(node, ClassVariableReadNode, ClassVariableWriteNode) end # Foo &&= bar @@ -45,12 +35,7 @@ module YARP # # Foo && Foo = bar def visit_constant_and_write_node(node) - AndNode.new( - ConstantReadNode.new(node.name_loc), - ConstantWriteNode.new(node.name_loc, node.value, node.operator_loc, node.location), - node.operator_loc, - node.location - ) + desugar_and_write_node(node, ConstantReadNode, ConstantWriteNode) end # Foo ||= bar @@ -59,12 +44,7 @@ module YARP # # Foo || Foo = bar def visit_constant_or_write_node(node) - OrNode.new( - ConstantReadNode.new(node.name_loc), - ConstantWriteNode.new(node.name_loc, node.value, node.operator_loc, node.location), - node.operator_loc, - node.location - ) + desugar_or_write_defined_node(node, ConstantReadNode, ConstantWriteNode) end # Foo += bar @@ -73,7 +53,7 @@ module YARP # # Foo = Foo + bar def visit_constant_operator_write_node(node) - desugar_operator_write_node(node, ConstantWriteNode, ConstantReadNode) + desugar_operator_write_node(node, ConstantReadNode, ConstantWriteNode) end # Foo::Bar &&= baz @@ -96,9 +76,19 @@ module YARP # # Foo::Bar || Foo::Bar = baz def visit_constant_path_or_write_node(node) - OrNode.new( - node.target, - ConstantPathWriteNode.new(node.target, node.value, node.operator_loc, node.location), + IfNode.new( + node.operator_loc, + DefinedNode.new(nil, node.target, nil, node.operator_loc, node.target.location), + StatementsNode.new([node.target], node.location), + ElseNode.new( + node.operator_loc, + StatementsNode.new( + [ConstantPathWriteNode.new(node.target, node.value, node.operator_loc, node.location)], + node.location + ), + node.operator_loc, + node.location + ), node.operator_loc, node.location ) @@ -135,12 +125,7 @@ module YARP # # $foo && $foo = bar def visit_global_variable_and_write_node(node) - AndNode.new( - GlobalVariableReadNode.new(node.name_loc), - GlobalVariableWriteNode.new(node.name_loc, node.value, node.operator_loc, node.location), - node.operator_loc, - node.location - ) + desugar_and_write_node(node, GlobalVariableReadNode, GlobalVariableWriteNode) end # $foo ||= bar @@ -149,12 +134,7 @@ module YARP # # $foo || $foo = bar def visit_global_variable_or_write_node(node) - OrNode.new( - GlobalVariableReadNode.new(node.name_loc), - GlobalVariableWriteNode.new(node.name_loc, node.value, node.operator_loc, node.location), - node.operator_loc, - node.location - ) + desugar_or_write_defined_node(node, GlobalVariableReadNode, GlobalVariableWriteNode) end # $foo += bar @@ -163,7 +143,7 @@ module YARP # # $foo = $foo + bar def visit_global_variable_operator_write_node(node) - desugar_operator_write_node(node, GlobalVariableWriteNode, GlobalVariableReadNode) + desugar_operator_write_node(node, GlobalVariableReadNode, GlobalVariableWriteNode) end # @foo &&= bar @@ -172,12 +152,7 @@ module YARP # # @foo && @foo = bar def visit_instance_variable_and_write_node(node) - AndNode.new( - InstanceVariableReadNode.new(node.name, node.name_loc), - InstanceVariableWriteNode.new(node.name, node.name_loc, node.value, node.operator_loc, node.location), - node.operator_loc, - node.location - ) + desugar_and_write_node(node, InstanceVariableReadNode, InstanceVariableWriteNode, arguments: [node.name]) end # @foo ||= bar @@ -186,12 +161,7 @@ module YARP # # @foo || @foo = bar def visit_instance_variable_or_write_node(node) - OrNode.new( - InstanceVariableReadNode.new(node.name, node.name_loc), - InstanceVariableWriteNode.new(node.name, node.name_loc, node.value, node.operator_loc, node.location), - node.operator_loc, - node.location - ) + desugar_or_write_node(node, InstanceVariableReadNode, InstanceVariableWriteNode, arguments: [node.name]) end # @foo += bar @@ -200,7 +170,7 @@ module YARP # # @foo = @foo + bar def visit_instance_variable_operator_write_node(node) - desugar_operator_write_node(node, InstanceVariableWriteNode, InstanceVariableReadNode, arguments: [node.name]) + desugar_operator_write_node(node, InstanceVariableReadNode, InstanceVariableWriteNode, arguments: [node.name]) end # foo &&= bar @@ -209,12 +179,7 @@ module YARP # # foo && foo = bar def visit_local_variable_and_write_node(node) - AndNode.new( - LocalVariableReadNode.new(node.name, node.depth, node.name_loc), - LocalVariableWriteNode.new(node.name, node.depth, node.name_loc, node.value, node.operator_loc, node.location), - node.operator_loc, - node.location - ) + desugar_and_write_node(node, LocalVariableReadNode, LocalVariableWriteNode, arguments: [node.name, node.depth]) end # foo ||= bar @@ -223,12 +188,7 @@ module YARP # # foo || foo = bar def visit_local_variable_or_write_node(node) - OrNode.new( - LocalVariableReadNode.new(node.name, node.depth, node.name_loc), - LocalVariableWriteNode.new(node.name, node.depth, node.name_loc, node.value, node.operator_loc, node.location), - node.operator_loc, - node.location - ) + desugar_or_write_node(node, LocalVariableReadNode, LocalVariableWriteNode, arguments: [node.name, node.depth]) end # foo += bar @@ -237,13 +197,23 @@ module YARP # # foo = foo + bar def visit_local_variable_operator_write_node(node) - desugar_operator_write_node(node, LocalVariableWriteNode, LocalVariableReadNode, arguments: [node.name, node.depth]) + desugar_operator_write_node(node, LocalVariableReadNode, LocalVariableWriteNode, arguments: [node.name, node.depth]) end private + # Desugar `x &&= y` to `x && x = y` + def desugar_and_write_node(node, read_class, write_class, arguments: []) + AndNode.new( + read_class.new(*arguments, node.name_loc), + write_class.new(*arguments, node.name_loc, node.value, node.operator_loc, node.location), + node.operator_loc, + node.location + ) + end + # Desugar `x += y` to `x = x + y` - def desugar_operator_write_node(node, write_class, read_class, arguments: []) + def desugar_operator_write_node(node, read_class, write_class, arguments: []) write_class.new( *arguments, node.name_loc, @@ -263,5 +233,35 @@ module YARP node.location ) end + + # Desugar `x ||= y` to `x || x = y` + def desugar_or_write_node(node, read_class, write_class, arguments: []) + OrNode.new( + read_class.new(*arguments, node.name_loc), + write_class.new(*arguments, node.name_loc, node.value, node.operator_loc, node.location), + node.operator_loc, + node.location + ) + end + + # Don't desugar `x ||= y` to `defined?(x) ? x : x = y` + def desugar_or_write_defined_node(node, read_class, write_class) + IfNode.new( + node.operator_loc, + DefinedNode.new(nil, read_class.new(node.name_loc), nil, node.operator_loc, node.name_loc), + StatementsNode.new([read_class.new(node.name_loc)], node.location), + ElseNode.new( + node.operator_loc, + StatementsNode.new( + [write_class.new(node.name_loc, node.value, node.operator_loc, node.location)], + node.location + ), + node.operator_loc, + node.location + ), + node.operator_loc, + node.location + ) + end end end |