зеркало из https://github.com/github/ruby.git
[ruby/prism] Reconfigure rationals
This eliminates the subnode on RationalNode and replaces it with two integer fields, which represent the ratio for the rational. It also reduces those two integers if they both fit into 32 bits. Importantly, this PR does not implement bignum reduction. That's something I'd like to consider for the future, but it's simple enough for now to leave them unreduced, which makes it more useful than it used to be. https://github.com/ruby/prism/commit/86e06c7068
This commit is contained in:
Родитель
42930d28a4
Коммит
89efb94fec
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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;
|
||||
|
@ -572,6 +575,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.
|
||||
*/
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
@ -100,6 +103,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.
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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: ∅
|
||||
|
|
|
@ -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) = "]"
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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: ∅
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
Загрузка…
Ссылка в новой задаче