summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/prism/node_ext.rb2
-rw-r--r--lib/prism/translation/parser/compiler.rb24
-rw-r--r--prism/config.yml17
-rw-r--r--prism/prism.c72
-rw-r--r--prism/static_literals.c118
-rw-r--r--prism/util/pm_integer.c38
-rw-r--r--prism/util/pm_integer.h15
-rw-r--r--test/prism/snapshots/numbers.txt73
-rw-r--r--test/prism/snapshots/patterns.txt42
-rw-r--r--test/prism/snapshots/seattlerb/ruby21_numbers.txt14
-rw-r--r--test/prism/snapshots/symbols.txt7
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/literal.txt26
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/literal.txt13
-rw-r--r--test/prism/snapshots/whitequark/complex.txt13
-rw-r--r--test/prism/snapshots/whitequark/rational.txt13
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_11873_a.txt24
16 files changed, 273 insertions, 238 deletions
diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb
index ceec76b8d6..4761e5b9b2 100644
--- a/lib/prism/node_ext.rb
+++ b/lib/prism/node_ext.rb
@@ -103,7 +103,7 @@ module Prism
class RationalNode < Node
# Returns the value of the node as a Ruby Rational.
def value
- Rational(numeric.is_a?(IntegerNode) ? numeric.value : slice.chomp("r"))
+ Rational(numerator, denominator)
end
end
diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb
index a6c3118efd..c3fa68231c 100644
--- a/lib/prism/translation/parser/compiler.rb
+++ b/lib/prism/translation/parser/compiler.rb
@@ -881,7 +881,7 @@ module Prism
# 1i
# ^^
def visit_imaginary_node(node)
- visit_numeric(node, builder.complex([imaginary_value(node), srange(node.location)]))
+ visit_numeric(node, builder.complex([Complex(0, node.numeric.value), srange(node.location)]))
end
# { foo: }
@@ -1514,7 +1514,7 @@ module Prism
# 1r
# ^^
def visit_rational_node(node)
- visit_numeric(node, builder.rational([rational_value(node), srange(node.location)]))
+ visit_numeric(node, builder.rational([node.value, srange(node.location)]))
end
# redo
@@ -1940,12 +1940,6 @@ 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,
@@ -1955,7 +1949,9 @@ module Prism
case receiver.type
when :integer_node, :float_node
receiver.copy(value: -receiver.value, location: message_loc.join(receiver.location))
- when :rational_node, :imaginary_node
+ when :rational_node
+ receiver.copy(numerator: -receiver.numerator, location: message_loc.join(receiver.location))
+ when :imaginary_node
receiver.copy(numeric: numeric_negate(message_loc, receiver.numeric), location: message_loc.join(receiver.location))
end
end
@@ -1974,16 +1970,6 @@ 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.
diff --git a/prism/config.yml b/prism/config.yml
index cfcfd2e7aa..08441ca4de 100644
--- a/prism/config.yml
+++ b/prism/config.yml
@@ -3231,8 +3231,21 @@ nodes:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- name: RationalNode
fields:
- - name: numeric
- type: node
+ - name: flags
+ type: flags
+ kind: IntegerBaseFlags
+ - name: numerator
+ type: integer
+ comment: |
+ The numerator of the rational number.
+
+ 1.5r # numerator 3
+ - name: denominator
+ type: integer
+ comment: |
+ The denominator of the rational number.
+
+ 1.5r # denominator 2
comment: |
Represents a rational number literal.
diff --git a/prism/prism.c b/prism/prism.c
index e146799393..a47aa08ce2 100644
--- a/prism/prism.c
+++ b/prism/prism.c
@@ -4290,7 +4290,7 @@ pm_float_node_imaginary_create(pm_parser_t *parser, const pm_token_t *token) {
}
/**
- * Allocate and initialize a new FloatNode node from a FLOAT_RATIONAL token.
+ * Allocate and initialize a new RationalNode node from a FLOAT_RATIONAL token.
*/
static pm_rational_node_t *
pm_float_node_rational_create(pm_parser_t *parser, const pm_token_t *token) {
@@ -4300,16 +4300,44 @@ pm_float_node_rational_create(pm_parser_t *parser, const pm_token_t *token) {
*node = (pm_rational_node_t) {
{
.type = PM_RATIONAL_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
+ .flags = PM_INTEGER_BASE_FLAGS_DECIMAL | PM_NODE_FLAG_STATIC_LITERAL,
.location = PM_LOCATION_TOKEN_VALUE(token)
},
- .numeric = (pm_node_t *) pm_float_node_create(parser, &((pm_token_t) {
- .type = PM_TOKEN_FLOAT,
- .start = token->start,
- .end = token->end - 1
- }))
+ .numerator = { 0 },
+ .denominator = { 0 }
};
+ const uint8_t *start = token->start;
+ const uint8_t *end = token->end - 1; // r
+
+ while (start < end && *start == '0') start++; // 0.1 -> .1
+ while (end > start && end[-1] == '0') end--; // 1.0 -> 1.
+
+ size_t length = (size_t) (end - start);
+ if (length == 1) {
+ node->denominator.value = 1;
+ return node;
+ }
+
+ const uint8_t *point = memchr(start, '.', length);
+ assert(point && "should have a decimal point");
+
+ uint8_t *digits = malloc(length - 1);
+ if (digits == NULL) {
+ fputs("[pm_float_node_rational_create] Failed to allocate memory", stderr);
+ abort();
+ }
+
+ memcpy(digits, start, (unsigned long) (point - start));
+ memcpy(digits + (point - start), point + 1, (unsigned long) (end - point - 1));
+ pm_integer_parse(&node->numerator, PM_INTEGER_BASE_DEFAULT, digits, digits + length - 1);
+
+ digits[0] = '1';
+ memset(digits + 1, '0', (size_t) (end - point - 1));
+ pm_integer_parse(&node->denominator, PM_INTEGER_BASE_DEFAULT, digits, digits + (end - point));
+ free(digits);
+
+ pm_integers_reduce(&node->numerator, &node->denominator);
return node;
}
@@ -4943,7 +4971,7 @@ pm_integer_node_imaginary_create(pm_parser_t *parser, pm_node_flags_t base, cons
}
/**
- * Allocate and initialize a new IntegerNode node from an INTEGER_RATIONAL
+ * Allocate and initialize a new RationalNode node from an INTEGER_RATIONAL
* token.
*/
static pm_rational_node_t *
@@ -4954,16 +4982,24 @@ pm_integer_node_rational_create(pm_parser_t *parser, pm_node_flags_t base, const
*node = (pm_rational_node_t) {
{
.type = PM_RATIONAL_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
+ .flags = base | PM_NODE_FLAG_STATIC_LITERAL,
.location = PM_LOCATION_TOKEN_VALUE(token)
},
- .numeric = (pm_node_t *) pm_integer_node_create(parser, base, &((pm_token_t) {
- .type = PM_TOKEN_INTEGER,
- .start = token->start,
- .end = token->end - 1
- }))
+ .numerator = { 0 },
+ .denominator = { .value = 1, 0 }
};
+ pm_integer_base_t integer_base = PM_INTEGER_BASE_DECIMAL;
+ switch (base) {
+ case PM_INTEGER_BASE_FLAGS_BINARY: integer_base = PM_INTEGER_BASE_BINARY; break;
+ case PM_INTEGER_BASE_FLAGS_OCTAL: integer_base = PM_INTEGER_BASE_OCTAL; break;
+ case PM_INTEGER_BASE_FLAGS_DECIMAL: break;
+ case PM_INTEGER_BASE_FLAGS_HEXADECIMAL: integer_base = PM_INTEGER_BASE_HEXADECIMAL; break;
+ default: assert(false && "unreachable"); break;
+ }
+
+ pm_integer_parse(&node->numerator, integer_base, token->start, token->end - 1);
+
return node;
}
@@ -16887,10 +16923,12 @@ parse_negative_numeric(pm_node_t *node) {
cast->value = -cast->value;
break;
}
- case PM_RATIONAL_NODE:
- node->location.start--;
- parse_negative_numeric(((pm_rational_node_t *) node)->numeric);
+ case PM_RATIONAL_NODE: {
+ pm_rational_node_t *cast = (pm_rational_node_t *) node;
+ cast->base.location.start--;
+ cast->numerator.negative = true;
break;
+ }
case PM_IMAGINARY_NODE:
node->location.start--;
parse_negative_numeric(((pm_imaginary_node_t *) node)->numeric);
diff --git a/prism/static_literals.c b/prism/static_literals.c
index 08f61c81fa..754a2d26b4 100644
--- a/prism/static_literals.c
+++ b/prism/static_literals.c
@@ -59,6 +59,25 @@ murmur_hash(const uint8_t *key, size_t length) {
}
/**
+ * Hash the value of an integer and return it.
+ */
+static uint32_t
+integer_hash(const pm_integer_t *integer) {
+ uint32_t hash;
+ if (integer->values) {
+ hash = murmur_hash((const uint8_t *) integer->values, sizeof(uint32_t) * integer->length);
+ } else {
+ hash = murmur_hash((const uint8_t *) &integer->value, sizeof(uint32_t));
+ }
+
+ if (integer->negative) {
+ hash ^= murmur_scramble((uint32_t) 1);
+ }
+
+ return hash;
+}
+
+/**
* Return the hash of the given node. It is important that nodes that have
* equivalent static literal values have the same hash. This is because we use
* these hashes to look for duplicates.
@@ -68,19 +87,8 @@ node_hash(const pm_static_literals_metadata_t *metadata, const pm_node_t *node)
switch (PM_NODE_TYPE(node)) {
case PM_INTEGER_NODE: {
// Integers hash their value.
- const pm_integer_t *integer = &((const pm_integer_node_t *) node)->value;
- uint32_t hash;
- if (integer->values) {
- hash = murmur_hash((const uint8_t *) integer->values, sizeof(uint32_t) * integer->length);
- } else {
- hash = murmur_hash((const uint8_t *) &integer->value, sizeof(uint32_t));
- }
-
- if (integer->negative) {
- hash ^= murmur_scramble((uint32_t) 1);
- }
-
- return hash;
+ const pm_integer_node_t *cast = (const pm_integer_node_t *) node;
+ return integer_hash(&cast->value);
}
case PM_SOURCE_LINE_NODE: {
// Source lines hash their line number.
@@ -94,11 +102,9 @@ node_hash(const pm_static_literals_metadata_t *metadata, const pm_node_t *node)
return murmur_hash((const uint8_t *) value, sizeof(double));
}
case PM_RATIONAL_NODE: {
- // Rationals hash their numeric value. Because their numeric value
- // is stored as a subnode, we hash that node and then mix in the
- // fact that this is a rational node.
- const pm_node_t *numeric = ((const pm_rational_node_t *) node)->numeric;
- return node_hash(metadata, numeric) ^ murmur_scramble((uint32_t) node->type);
+ // Rationals hash their numerator and denominator.
+ const pm_rational_node_t *cast = (const pm_rational_node_t *) node;
+ return integer_hash(&cast->numerator) ^ integer_hash(&cast->denominator) ^ murmur_scramble((uint32_t) cast->base.type);
}
case PM_IMAGINARY_NODE: {
// Imaginaries hash their numeric value. Because their numeric value
@@ -275,8 +281,15 @@ pm_compare_number_nodes(const pm_static_literals_metadata_t *metadata, const pm_
switch (PM_NODE_TYPE(left)) {
case PM_IMAGINARY_NODE:
return pm_compare_number_nodes(metadata, ((const pm_imaginary_node_t *) left)->numeric, ((const pm_imaginary_node_t *) right)->numeric);
- case PM_RATIONAL_NODE:
- return pm_compare_number_nodes(metadata, ((const pm_rational_node_t *) left)->numeric, ((const pm_rational_node_t *) right)->numeric);
+ case PM_RATIONAL_NODE: {
+ const pm_rational_node_t *left_rational = (const pm_rational_node_t *) left;
+ const pm_rational_node_t *right_rational = (const pm_rational_node_t *) right;
+
+ int result = pm_integer_compare(&left_rational->denominator, &right_rational->denominator);
+ if (result != 0) return result;
+
+ return pm_integer_compare(&left_rational->numerator, &right_rational->numerator);
+ }
case PM_INTEGER_NODE:
return pm_compare_integer_nodes(metadata, left, right);
case PM_FLOAT_NODE:
@@ -456,7 +469,7 @@ pm_static_literal_positive_p(const pm_node_t *node) {
case PM_INTEGER_NODE:
return !((const pm_integer_node_t *) node)->value.negative;
case PM_RATIONAL_NODE:
- return pm_static_literal_positive_p(((const pm_rational_node_t *) node)->numeric);
+ return !((const pm_rational_node_t *) node)->numerator.negative;
case PM_IMAGINARY_NODE:
return pm_static_literal_positive_p(((const pm_imaginary_node_t *) node)->numeric);
default:
@@ -466,43 +479,6 @@ pm_static_literal_positive_p(const pm_node_t *node) {
}
/**
- * Inspect a rational node that wraps a float node. This is going to be a
- * poor-man's version of the Ruby `Rational#to_s` method, because we're not
- * going to try to reduce the rational by finding the GCD. We'll leave that for
- * a future improvement.
- */
-static void
-pm_rational_inspect(pm_buffer_t *buffer, pm_rational_node_t *node) {
- const uint8_t *start = node->base.location.start;
- const uint8_t *end = node->base.location.end - 1; // r
-
- while (start < end && *start == '0') start++; // 0.1 -> .1
- while (end > start && end[-1] == '0') end--; // 1.0 -> 1.
- size_t length = (size_t) (end - start);
-
- const uint8_t *point = memchr(start, '.', length);
- assert(point && "should have a decimal point");
-
- uint8_t *digits = malloc(length - 1);
- if (digits == NULL) return;
-
- memcpy(digits, start, (unsigned long) (point - start));
- memcpy(digits + (point - start), point + 1, (unsigned long) (end - point - 1));
-
- pm_integer_t numerator = { 0 };
- pm_integer_parse(&numerator, PM_INTEGER_BASE_DECIMAL, digits, digits + length - 1);
-
- pm_buffer_append_byte(buffer, '(');
- pm_integer_string(buffer, &numerator);
- pm_buffer_append_string(buffer, "/1", 2);
- for (size_t index = 0; index < (size_t) (end - point - 1); index++) pm_buffer_append_byte(buffer, '0');
- pm_buffer_append_byte(buffer, ')');
-
- pm_integer_free(&numerator);
- free(digits);
-}
-
-/**
* Create a string-based representation of the given static literal.
*/
static inline void
@@ -544,7 +520,9 @@ pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_met
pm_buffer_append_string(buffer, "(0", 2);
if (pm_static_literal_positive_p(numeric)) pm_buffer_append_byte(buffer, '+');
pm_static_literal_inspect_node(buffer, metadata, numeric);
- if (PM_NODE_TYPE_P(numeric, PM_RATIONAL_NODE)) pm_buffer_append_byte(buffer, '*');
+ if (PM_NODE_TYPE_P(numeric, PM_RATIONAL_NODE)) {
+ pm_buffer_append_byte(buffer, '*');
+ }
pm_buffer_append_string(buffer, "i)", 2);
break;
}
@@ -555,22 +533,12 @@ pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_met
pm_buffer_append_string(buffer, "nil", 3);
break;
case PM_RATIONAL_NODE: {
- const pm_node_t *numeric = ((const pm_rational_node_t *) node)->numeric;
-
- switch (PM_NODE_TYPE(numeric)) {
- case PM_INTEGER_NODE:
- pm_buffer_append_byte(buffer, '(');
- pm_static_literal_inspect_node(buffer, metadata, numeric);
- pm_buffer_append_string(buffer, "/1)", 3);
- break;
- case PM_FLOAT_NODE:
- pm_rational_inspect(buffer, (pm_rational_node_t *) node);
- break;
- default:
- assert(false && "unreachable");
- break;
- }
-
+ const pm_rational_node_t *rational = (const pm_rational_node_t *) node;
+ pm_buffer_append_byte(buffer, '(');
+ pm_integer_string(buffer, &rational->numerator);
+ pm_buffer_append_byte(buffer, '/');
+ pm_integer_string(buffer, &rational->denominator);
+ pm_buffer_append_byte(buffer, ')');
break;
}
case PM_REGULAR_EXPRESSION_NODE: {
diff --git a/prism/util/pm_integer.c b/prism/util/pm_integer.c
index e523bae90b..015789ccec 100644
--- a/prism/util/pm_integer.c
+++ b/prism/util/pm_integer.c
@@ -473,13 +473,16 @@ pm_integer_parse_big(pm_integer_t *integer, uint32_t multiplier, const uint8_t *
*/
PRISM_EXPORTED_FUNCTION void
pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *start, const uint8_t *end) {
- // Ignore unary +. Unary + is parsed differently and will not end up here.
+ // Ignore unary +. Unary - is parsed differently and will not end up here.
// Instead, it will modify the parsed integer later.
if (*start == '+') start++;
// Determine the multiplier from the base, and skip past any prefixes.
uint32_t multiplier = 10;
switch (base) {
+ case PM_INTEGER_BASE_DEFAULT:
+ while (*start == '0') start++; // 01 -> 1
+ break;
case PM_INTEGER_BASE_BINARY:
start += 2; // 0b
multiplier = 2;
@@ -573,6 +576,39 @@ pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right) {
}
/**
+ * Reduce a ratio of integers to its simplest form.
+ */
+void pm_integers_reduce(pm_integer_t *numerator, pm_integer_t *denominator) {
+ // If either the numerator or denominator do not fit into a 32-bit integer,
+ // then this function is a no-op. In the future, we may consider reducing
+ // even the larger numbers, but for now we're going to keep it simple.
+ if (
+ // If the numerator doesn't fit into a 32-bit integer, return early.
+ numerator->length != 0 ||
+ // If the denominator doesn't fit into a 32-bit integer, return early.
+ denominator->length != 0 ||
+ // If the numerator is 0, then return early.
+ numerator->value == 0 ||
+ // If the denominator is 1, then return early.
+ denominator->value == 1
+ ) return;
+
+ // Find the greatest common divisor of the numerator and denominator.
+ uint32_t divisor = numerator->value;
+ uint32_t remainder = denominator->value;
+
+ while (remainder != 0) {
+ uint32_t temporary = remainder;
+ remainder = divisor % remainder;
+ divisor = temporary;
+ }
+
+ // Divide the numerator and denominator by the greatest common divisor.
+ numerator->value /= divisor;
+ denominator->value /= divisor;
+}
+
+/**
* Convert an integer to a decimal string.
*/
PRISM_EXPORTED_FUNCTION void
diff --git a/prism/util/pm_integer.h b/prism/util/pm_integer.h
index 7f172988b3..d2a1808b19 100644
--- a/prism/util/pm_integer.h
+++ b/prism/util/pm_integer.h
@@ -48,6 +48,9 @@ typedef struct {
* from the string itself.
*/
typedef enum {
+ /** The default decimal base, with no prefix. Leading 0s will be ignored. */
+ PM_INTEGER_BASE_DEFAULT,
+
/** The binary base, indicated by a 0b or 0B prefix. */
PM_INTEGER_BASE_BINARY,
@@ -101,6 +104,18 @@ size_t pm_integer_memsize(const pm_integer_t *integer);
int pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right);
/**
+ * Reduce a ratio of integers to its simplest form.
+ *
+ * If either the numerator or denominator do not fit into a 32-bit integer, then
+ * this function is a no-op. In the future, we may consider reducing even the
+ * larger numbers, but for now we're going to keep it simple.
+ *
+ * @param numerator The numerator of the ratio.
+ * @param denominator The denominator of the ratio.
+ */
+void pm_integers_reduce(pm_integer_t *numerator, pm_integer_t *denominator);
+
+/**
* Convert an integer to a decimal string.
*
* @param buffer The buffer to append the string to.
diff --git a/test/prism/snapshots/numbers.txt b/test/prism/snapshots/numbers.txt
index 740f3f5a2a..58aea454fa 100644
--- a/test/prism/snapshots/numbers.txt
+++ b/test/prism/snapshots/numbers.txt
@@ -65,52 +65,48 @@
│ ├── flags: decimal
│ └── value: 1
├── @ RationalNode (location: (41,0)-(41,2))
- │ └── numeric:
- │ @ IntegerNode (location: (41,0)-(41,1))
- │ ├── flags: decimal
- │ └── value: 1
+ │ ├── flags: decimal
+ │ ├── numerator: 1
+ │ └── denominator: 1
├── @ IntegerNode (location: (43,0)-(43,2))
│ ├── flags: decimal
│ └── value: -1
├── @ ImaginaryNode (location: (45,0)-(45,3))
│ └── numeric:
│ @ RationalNode (location: (45,0)-(45,2))
- │ └── numeric:
- │ @ IntegerNode (location: (45,0)-(45,1))
- │ ├── flags: decimal
- │ └── value: 1
+ │ ├── flags: decimal
+ │ ├── numerator: 1
+ │ └── denominator: 1
├── @ RationalNode (location: (47,0)-(47,4))
- │ └── numeric:
- │ @ FloatNode (location: (47,0)-(47,3))
- │ └── value: 1.2
+ │ ├── flags: decimal
+ │ ├── numerator: 6
+ │ └── denominator: 5
├── @ ImaginaryNode (location: (49,0)-(49,5))
│ └── numeric:
│ @ RationalNode (location: (49,0)-(49,4))
- │ └── numeric:
- │ @ FloatNode (location: (49,0)-(49,3))
- │ └── value: 1.2
+ │ ├── flags: decimal
+ │ ├── numerator: 6
+ │ └── denominator: 5
├── @ ImaginaryNode (location: (51,0)-(51,4))
│ └── numeric:
│ @ RationalNode (location: (51,0)-(51,3))
- │ └── numeric:
- │ @ IntegerNode (location: (51,0)-(51,2))
- │ ├── flags: decimal
- │ └── value: -1
+ │ ├── flags: decimal
+ │ ├── numerator: -1
+ │ └── denominator: 1
├── @ RationalNode (location: (53,0)-(53,5))
- │ └── numeric:
- │ @ FloatNode (location: (53,0)-(53,4))
- │ └── value: -1.2
+ │ ├── flags: decimal
+ │ ├── numerator: -6
+ │ └── denominator: 5
├── @ ImaginaryNode (location: (55,0)-(55,6))
│ └── numeric:
│ @ RationalNode (location: (55,0)-(55,5))
- │ └── numeric:
- │ @ FloatNode (location: (55,0)-(55,4))
- │ └── value: -1.2
+ │ ├── flags: decimal
+ │ ├── numerator: -6
+ │ └── denominator: 5
├── @ RationalNode (location: (57,0)-(57,4))
- │ └── numeric:
- │ @ IntegerNode (location: (57,0)-(57,3))
- │ ├── flags: octal
- │ └── value: 1
+ │ ├── flags: octal
+ │ ├── numerator: 1
+ │ └── denominator: 1
├── @ ImaginaryNode (location: (59,0)-(59,4))
│ └── numeric:
│ @ IntegerNode (location: (59,0)-(59,3))
@@ -119,15 +115,13 @@
├── @ ImaginaryNode (location: (61,0)-(61,5))
│ └── numeric:
│ @ RationalNode (location: (61,0)-(61,4))
- │ └── numeric:
- │ @ IntegerNode (location: (61,0)-(61,3))
- │ ├── flags: octal
- │ └── value: 1
+ │ ├── flags: octal
+ │ ├── numerator: 1
+ │ └── denominator: 1
├── @ RationalNode (location: (63,0)-(63,4))
- │ └── numeric:
- │ @ IntegerNode (location: (63,0)-(63,3))
- │ ├── flags: decimal
- │ └── value: 1
+ │ ├── flags: decimal
+ │ ├── numerator: 1
+ │ └── denominator: 1
├── @ ImaginaryNode (location: (65,0)-(65,4))
│ └── numeric:
│ @ IntegerNode (location: (65,0)-(65,3))
@@ -136,7 +130,6 @@
└── @ ImaginaryNode (location: (67,0)-(67,5))
└── numeric:
@ RationalNode (location: (67,0)-(67,4))
- └── numeric:
- @ IntegerNode (location: (67,0)-(67,3))
- ├── flags: binary
- └── value: 1
+ ├── flags: binary
+ ├── numerator: 1
+ └── denominator: 1
diff --git a/test/prism/snapshots/patterns.txt b/test/prism/snapshots/patterns.txt
index 16298e7984..17aa23b4b9 100644
--- a/test/prism/snapshots/patterns.txt
+++ b/test/prism/snapshots/patterns.txt
@@ -86,10 +86,9 @@
│ │ └── block: ∅
│ ├── pattern:
│ │ @ RationalNode (location: (5,7)-(5,9))
- │ │ └── numeric:
- │ │ @ IntegerNode (location: (5,7)-(5,8))
- │ │ ├── flags: decimal
- │ │ └── value: 1
+ │ │ ├── flags: decimal
+ │ │ ├── numerator: 1
+ │ │ └── denominator: 1
│ └── operator_loc: (5,4)-(5,6) = "=>"
├── @ MatchRequiredNode (location: (6,0)-(6,11))
│ ├── value:
@@ -598,16 +597,14 @@
│ │ ├── flags: ∅
│ │ ├── left:
│ │ │ @ RationalNode (location: (31,7)-(31,9))
- │ │ │ └── numeric:
- │ │ │ @ IntegerNode (location: (31,7)-(31,8))
- │ │ │ ├── flags: decimal
- │ │ │ └── value: 1
+ │ │ │ ├── flags: decimal
+ │ │ │ ├── numerator: 1
+ │ │ │ └── denominator: 1
│ │ ├── right:
│ │ │ @ RationalNode (location: (31,13)-(31,15))
- │ │ │ └── numeric:
- │ │ │ @ IntegerNode (location: (31,13)-(31,14))
- │ │ │ ├── flags: decimal
- │ │ │ └── value: 1
+ │ │ │ ├── flags: decimal
+ │ │ │ ├── numerator: 1
+ │ │ │ └── denominator: 1
│ │ └── operator_loc: (31,10)-(31,12) = ".."
│ └── operator_loc: (31,4)-(31,6) = "=>"
├── @ MatchRequiredNode (location: (32,0)-(32,19))
@@ -2461,10 +2458,9 @@
│ │ └── block: ∅
│ ├── pattern:
│ │ @ RationalNode (location: (108,7)-(108,9))
- │ │ └── numeric:
- │ │ @ IntegerNode (location: (108,7)-(108,8))
- │ │ ├── flags: decimal
- │ │ └── value: 1
+ │ │ ├── flags: decimal
+ │ │ ├── numerator: 1
+ │ │ └── denominator: 1
│ └── operator_loc: (108,4)-(108,6) = "in"
├── @ MatchPredicateNode (location: (109,0)-(109,11))
│ ├── value:
@@ -3017,10 +3013,9 @@
│ │ └── @ InNode (location: (139,10)-(139,20))
│ │ ├── pattern:
│ │ │ @ RationalNode (location: (139,13)-(139,15))
- │ │ │ └── numeric:
- │ │ │ @ IntegerNode (location: (139,13)-(139,14))
- │ │ │ ├── flags: decimal
- │ │ │ └── value: 1
+ │ │ │ ├── flags: decimal
+ │ │ │ ├── numerator: 1
+ │ │ │ └── denominator: 1
│ │ ├── statements: ∅
│ │ ├── in_loc: (139,10)-(139,12) = "in"
│ │ └── then_loc: (139,16)-(139,20) = "then"
@@ -3758,10 +3753,9 @@
│ │ │ │ @ StatementsNode (location: (166,13)-(166,15))
│ │ │ │ └── body: (length: 1)
│ │ │ │ └── @ RationalNode (location: (166,13)-(166,15))
- │ │ │ │ └── numeric:
- │ │ │ │ @ IntegerNode (location: (166,13)-(166,14))
- │ │ │ │ ├── flags: decimal
- │ │ │ │ └── value: 1
+ │ │ │ │ ├── flags: decimal
+ │ │ │ │ ├── numerator: 1
+ │ │ │ │ └── denominator: 1
│ │ │ ├── consequent: ∅
│ │ │ └── end_keyword_loc: ∅
│ │ ├── statements: ∅
diff --git a/test/prism/snapshots/seattlerb/ruby21_numbers.txt b/test/prism/snapshots/seattlerb/ruby21_numbers.txt
index 34a3452d1b..e7eec943f8 100644
--- a/test/prism/snapshots/seattlerb/ruby21_numbers.txt
+++ b/test/prism/snapshots/seattlerb/ruby21_numbers.txt
@@ -12,16 +12,14 @@
│ │ ├── flags: decimal
│ │ └── value: 1
│ ├── @ RationalNode (location: (1,5)-(1,7))
- │ │ └── numeric:
- │ │ @ IntegerNode (location: (1,5)-(1,6))
- │ │ ├── flags: decimal
- │ │ └── value: 2
+ │ │ ├── flags: decimal
+ │ │ ├── numerator: 2
+ │ │ └── denominator: 1
│ └── @ ImaginaryNode (location: (1,9)-(1,12))
│ └── numeric:
│ @ RationalNode (location: (1,9)-(1,11))
- │ └── numeric:
- │ @ IntegerNode (location: (1,9)-(1,10))
- │ ├── flags: decimal
- │ └── value: 3
+ │ ├── flags: decimal
+ │ ├── numerator: 3
+ │ └── denominator: 1
├── opening_loc: (1,0)-(1,1) = "["
└── closing_loc: (1,12)-(1,13) = "]"
diff --git a/test/prism/snapshots/symbols.txt b/test/prism/snapshots/symbols.txt
index dbd3a4d030..48ff0d634f 100644
--- a/test/prism/snapshots/symbols.txt
+++ b/test/prism/snapshots/symbols.txt
@@ -146,10 +146,9 @@
│ │ ├── @ FloatNode (location: (29,4)-(29,7))
│ │ │ └── value: 1.0
│ │ ├── @ RationalNode (location: (29,9)-(29,11))
- │ │ │ └── numeric:
- │ │ │ @ IntegerNode (location: (29,9)-(29,10))
- │ │ │ ├── flags: decimal
- │ │ │ └── value: 1
+ │ │ │ ├── flags: decimal
+ │ │ │ ├── numerator: 1
+ │ │ │ └── denominator: 1
│ │ └── @ ImaginaryNode (location: (29,13)-(29,15))
│ │ └── numeric:
│ │ @ IntegerNode (location: (29,13)-(29,14))
diff --git a/test/prism/snapshots/unparser/corpus/literal/literal.txt b/test/prism/snapshots/unparser/corpus/literal/literal.txt
index 98b88e11ce..ddb10456bf 100644
--- a/test/prism/snapshots/unparser/corpus/literal/literal.txt
+++ b/test/prism/snapshots/unparser/corpus/literal/literal.txt
@@ -316,18 +316,17 @@
│ ├── flags: decimal
│ └── value: 1
├── @ RationalNode (location: (19,0)-(19,2))
- │ └── numeric:
- │ @ IntegerNode (location: (19,0)-(19,1))
- │ ├── flags: decimal
- │ └── value: 1
+ │ ├── flags: decimal
+ │ ├── numerator: 1
+ │ └── denominator: 1
├── @ RationalNode (location: (20,0)-(20,4))
- │ └── numeric:
- │ @ FloatNode (location: (20,0)-(20,3))
- │ └── value: 1.5
+ │ ├── flags: decimal
+ │ ├── numerator: 3
+ │ └── denominator: 2
├── @ RationalNode (location: (21,0)-(21,4))
- │ └── numeric:
- │ @ FloatNode (location: (21,0)-(21,3))
- │ └── value: 1.3
+ │ ├── flags: decimal
+ │ ├── numerator: 13
+ │ └── denominator: 10
├── @ ImaginaryNode (location: (22,0)-(22,2))
│ └── numeric:
│ @ IntegerNode (location: (22,0)-(22,1))
@@ -354,10 +353,9 @@
├── @ ImaginaryNode (location: (27,0)-(27,3))
│ └── numeric:
│ @ RationalNode (location: (27,0)-(27,2))
- │ └── numeric:
- │ @ IntegerNode (location: (27,0)-(27,1))
- │ ├── flags: decimal
- │ └── value: 1
+ │ ├── flags: decimal
+ │ ├── numerator: 1
+ │ └── denominator: 1
├── @ InterpolatedStringNode (location: (28,0)-(28,11))
│ ├── flags: ∅
│ ├── opening_loc: ∅
diff --git a/test/prism/snapshots/unparser/corpus/semantic/literal.txt b/test/prism/snapshots/unparser/corpus/semantic/literal.txt
index ef666890be..448207f5d3 100644
--- a/test/prism/snapshots/unparser/corpus/semantic/literal.txt
+++ b/test/prism/snapshots/unparser/corpus/semantic/literal.txt
@@ -4,14 +4,13 @@
@ StatementsNode (location: (1,0)-(14,10))
└── body: (length: 14)
├── @ RationalNode (location: (1,0)-(1,4))
- │ └── numeric:
- │ @ FloatNode (location: (1,0)-(1,3))
- │ └── value: 1.0
+ │ ├── flags: decimal
+ │ ├── numerator: 1
+ │ └── denominator: 1
├── @ RationalNode (location: (2,0)-(2,3))
- │ └── numeric:
- │ @ IntegerNode (location: (2,0)-(2,2))
- │ ├── flags: decimal
- │ └── value: 0
+ │ ├── flags: decimal
+ │ ├── numerator: 0
+ │ └── denominator: 1
├── @ IntegerNode (location: (3,0)-(3,3))
│ ├── flags: hexadecimal
│ └── value: 1
diff --git a/test/prism/snapshots/whitequark/complex.txt b/test/prism/snapshots/whitequark/complex.txt
index e688585a5f..bc748db09b 100644
--- a/test/prism/snapshots/whitequark/complex.txt
+++ b/test/prism/snapshots/whitequark/complex.txt
@@ -10,9 +10,9 @@
├── @ ImaginaryNode (location: (3,0)-(3,6))
│ └── numeric:
│ @ RationalNode (location: (3,0)-(3,5))
- │ └── numeric:
- │ @ FloatNode (location: (3,0)-(3,4))
- │ └── value: 42.1
+ │ ├── flags: decimal
+ │ ├── numerator: 421
+ │ └── denominator: 10
├── @ ImaginaryNode (location: (5,0)-(5,3))
│ └── numeric:
│ @ IntegerNode (location: (5,0)-(5,2))
@@ -21,7 +21,6 @@
└── @ ImaginaryNode (location: (7,0)-(7,4))
└── numeric:
@ RationalNode (location: (7,0)-(7,3))
- └── numeric:
- @ IntegerNode (location: (7,0)-(7,2))
- ├── flags: decimal
- └── value: 42
+ ├── flags: decimal
+ ├── numerator: 42
+ └── denominator: 1
diff --git a/test/prism/snapshots/whitequark/rational.txt b/test/prism/snapshots/whitequark/rational.txt
index 90bbd17929..e8c8eed508 100644
--- a/test/prism/snapshots/whitequark/rational.txt
+++ b/test/prism/snapshots/whitequark/rational.txt
@@ -4,11 +4,10 @@
@ StatementsNode (location: (1,0)-(3,3))
└── body: (length: 2)
├── @ RationalNode (location: (1,0)-(1,5))
- │ └── numeric:
- │ @ FloatNode (location: (1,0)-(1,4))
- │ └── value: 42.1
+ │ ├── flags: decimal
+ │ ├── numerator: 421
+ │ └── denominator: 10
└── @ RationalNode (location: (3,0)-(3,3))
- └── numeric:
- @ IntegerNode (location: (3,0)-(3,2))
- ├── flags: decimal
- └── value: 42
+ ├── flags: decimal
+ ├── numerator: 42
+ └── denominator: 1
diff --git a/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt b/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt
index 93418e6448..831d57e30d 100644
--- a/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt
+++ b/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt
@@ -225,9 +225,9 @@
│ │ │ ├── closing_loc: (7,7)-(7,8) = ")"
│ │ │ └── block: ∅
│ │ └── @ RationalNode (location: (7,10)-(7,14))
- │ │ └── numeric:
- │ │ @ FloatNode (location: (7,10)-(7,13))
- │ │ └── value: 1.0
+ │ │ ├── flags: decimal
+ │ │ ├── numerator: 1
+ │ │ └── denominator: 1
│ ├── closing_loc: ∅
│ └── block:
│ @ BlockNode (location: (7,15)-(7,21))
@@ -519,9 +519,9 @@
│ │ │ ├── closing_loc: (17,8)-(17,9) = ")"
│ │ │ └── block: ∅
│ │ └── @ RationalNode (location: (17,11)-(17,15))
- │ │ └── numeric:
- │ │ @ FloatNode (location: (17,11)-(17,14))
- │ │ └── value: 1.0
+ │ │ ├── flags: decimal
+ │ │ ├── numerator: 1
+ │ │ └── denominator: 1
│ ├── closing_loc: ∅
│ └── block:
│ @ BlockNode (location: (17,16)-(17,22))
@@ -833,9 +833,9 @@
│ │ │ ├── opening_loc: (27,3)-(27,4) = "{"
│ │ │ └── closing_loc: (27,7)-(27,8) = "}"
│ │ └── @ RationalNode (location: (27,10)-(27,14))
- │ │ └── numeric:
- │ │ @ FloatNode (location: (27,10)-(27,13))
- │ │ └── value: 1.0
+ │ │ ├── flags: decimal
+ │ │ ├── numerator: 1
+ │ │ └── denominator: 1
│ ├── closing_loc: ∅
│ └── block:
│ @ BlockNode (location: (27,15)-(27,21))
@@ -1152,9 +1152,9 @@
│ │ │ ├── opening_loc: (37,3)-(37,4) = "{"
│ │ │ └── closing_loc: (37,8)-(37,9) = "}"
│ │ └── @ RationalNode (location: (37,11)-(37,15))
- │ │ └── numeric:
- │ │ @ FloatNode (location: (37,11)-(37,14))
- │ │ └── value: 1.0
+ │ │ ├── flags: decimal
+ │ │ ├── numerator: 1
+ │ │ └── denominator: 1
│ ├── closing_loc: ∅
│ └── block:
│ @ BlockNode (location: (37,16)-(37,22))