diff options
author | Kevin Newton <kddnewton@gmail.com> | 2024-02-26 09:18:17 -0500 |
---|---|---|
committer | git <svn-admin@ruby-lang.org> | 2024-02-26 14:26:53 +0000 |
commit | af3145bb2446f27f895e78cfab49eea23fad8865 (patch) | |
tree | 877621ce6d0774a511cd76f89521a0482c099fa6 /lib/prism/translation/parser/compiler.rb | |
parent | 83e676e5f9049168047c36d1bbd75ac342e6fed6 (diff) |
[ruby/prism] Handle negated numeric in parser translation
https://github.com/ruby/prism/commit/5877a95be4
Diffstat (limited to 'lib/prism/translation/parser/compiler.rb')
-rw-r--r-- | lib/prism/translation/parser/compiler.rb | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb index 423df8fb8c..c8ab3740bd 100644 --- a/lib/prism/translation/parser/compiler.rb +++ b/lib/prism/translation/parser/compiler.rb @@ -247,6 +247,11 @@ module Prism if node.call_operator_loc.nil? case name + when :-@ + case (receiver = node.receiver).type + when :integer_node, :float_node, :rational_node, :imaginary_node + return visit(numeric_negate(node.message_loc, receiver)) + end when :! return visit_block(builder.not_op(token(node.message_loc), token(node.opening_loc), visit(node.receiver), token(node.closing_loc)), block) when :[] @@ -792,7 +797,7 @@ module Prism # 1i def visit_imaginary_node(node) - visit_numeric(node, builder.complex([node.value, srange(node.location)])) + visit_numeric(node, builder.complex([imaginary_value(node), srange(node.location)])) end # { foo: } @@ -1325,7 +1330,7 @@ module Prism # 1r # ^^ def visit_rational_node(node) - visit_numeric(node, builder.rational([node.value, srange(node.location)])) + visit_numeric(node, builder.rational([rational_value(node), srange(node.location)])) end # redo @@ -1690,6 +1695,26 @@ module Prism forwarding end + # Because we have mutated the AST to allow for newlines in the middle of + # a rational, we need to manually handle the value here. + def imaginary_value(node) + Complex(0, node.numeric.is_a?(RationalNode) ? rational_value(node.numeric) : node.numeric.value) + end + + # Negate the value of a numeric node. This is a special case where you + # have a negative sign on one line and then a number on the next line. + # In normal Ruby, this will always be a method call. The parser gem, + # however, marks this as a numeric literal. We have to massage the tree + # here to get it into the correct form. + def numeric_negate(message_loc, receiver) + case receiver.type + when :integer_node, :float_node + receiver.copy(value: -receiver.value, location: message_loc.join(receiver.location)) + when :rational_node, :imaginary_node + receiver.copy(numeric: numeric_negate(message_loc, receiver.numeric), location: message_loc.join(receiver.location)) + end + end + # Blocks can have a special set of parameters that automatically expand # when given arrays if they have a single required parameter and no # other parameters. @@ -1704,6 +1729,16 @@ module Prism parameters.block.nil? end + # Because we have mutated the AST to allow for newlines in the middle of + # a rational, we need to manually handle the value here. + def rational_value(node) + if node.numeric.is_a?(IntegerNode) + Rational(node.numeric.value) + else + Rational(node.slice.gsub(/\s/, "").chomp("r")) + end + end + # Locations in the parser gem AST are generated using this class. We # store a reference to its constant to make it slightly faster to look # up. |