diff --git a/config.yml b/config.yml index 6b4b1aa9c0e..6e0ce1ce1ee 100644 --- a/config.yml +++ b/config.yml @@ -3229,8 +3229,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/include/prism/util/pm_integer.h b/include/prism/util/pm_integer.h index 7f172988b3e..56a4c5cc672 100644 --- a/include/prism/util/pm_integer.h +++ b/include/prism/util/pm_integer.h @@ -100,6 +100,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. * diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index ceec76b8d6a..4761e5b9b27 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -103,7 +103,7 @@ def value 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 a6c3118efd1..c3fa68231ce 100644 --- a/lib/prism/translation/parser/compiler.rb +++ b/lib/prism/translation/parser/compiler.rb @@ -881,7 +881,7 @@ def visit_if_node(node) # 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 @@ def visit_range_node(node) # 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 @@ def find_forwarding(node) 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 @@ 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 + 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 @@ def procarg0?(parameters) 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/src/prism.c b/src/prism.c index a382d070e57..038878104c4 100644 --- a/src/prism.c +++ b/src/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,39 @@ 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); + 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_DECIMAL, digits, digits + length - 1); + + digits[0] = '1'; + memset(digits + 1, '0', (size_t) (end - point - 1)); + pm_integer_parse(&node->denominator, PM_INTEGER_BASE_DECIMAL, digits, digits + (end - point)); + free(digits); + + pm_integers_reduce(&node->numerator, &node->denominator); return node; } @@ -4943,7 +4966,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 +4977,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; } @@ -16857,10 +16888,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/src/static_literals.c b/src/static_literals.c index 08f61c81fa1..754a2d26b4a 100644 --- a/src/static_literals.c +++ b/src/static_literals.c @@ -58,6 +58,25 @@ murmur_hash(const uint8_t *key, size_t length) { return hash; } +/** + * 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 @@ -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: @@ -465,43 +478,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. */ @@ -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/src/util/pm_integer.c b/src/util/pm_integer.c index e523bae90b1..d8c85436f5a 100644 --- a/src/util/pm_integer.c +++ b/src/util/pm_integer.c @@ -473,7 +473,7 @@ 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++; @@ -572,6 +572,39 @@ pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right) { return 0; } +/** + * 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. */ diff --git a/test/prism/snapshots/numbers.txt b/test/prism/snapshots/numbers.txt index 740f3f5a2a1..58aea454fa0 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 16298e79849..17aa23b4b94 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 34a3452d1b3..e7eec943f82 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 dbd3a4d030d..48ff0d634fa 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 98b88e11ceb..ddb10456bf0 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 ef666890be7..448207f5d37 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 e688585a5f9..bc748db09bb 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 90bbd17929b..e8c8eed5082 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 93418e64483..831d57e30d3 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))