diff options
author | Kevin Newton <kddnewton@gmail.com> | 2023-09-05 14:16:33 -0400 |
---|---|---|
committer | git <svn-admin@ruby-lang.org> | 2023-09-05 19:13:30 +0000 |
commit | 767f984017ca264262d9ef04d1db78c6f361e65a (patch) | |
tree | 3428a915393cb0fb99d0248fcfce3238f0bc9717 /yarp | |
parent | 95e4bdcd6263a8106eac25458a48517aaa4456f8 (diff) |
[ruby/yarp] Flatten CallAndWriteNode, CallOrWriteNode, and CallOperatorWriteNode
https://github.com/ruby/yarp/commit/8f26ffa0b2
Diffstat (limited to 'yarp')
-rw-r--r-- | yarp/config.yml | 109 | ||||
-rw-r--r-- | yarp/yarp.c | 95 |
2 files changed, 157 insertions, 47 deletions
diff --git a/yarp/config.yml b/yarp/config.yml index 4c4ac81ac3..a53b7aaa86 100644 --- a/yarp/config.yml +++ b/yarp/config.yml @@ -591,6 +591,37 @@ nodes: break foo ^^^^^^^^^ + - name: CallAndWriteNode + fields: + - name: receiver + type: node? + - name: call_operator_loc + type: location? + - name: message_loc + type: location? + - name: opening_loc + type: location? + - name: arguments + type: node? + kind: ArgumentsNode + - name: closing_loc + type: location? + - name: flags + type: flags + kind: CallNodeFlags + - name: read_name + type: string + - name: write_name + type: string + - name: operator_loc + type: location + - name: value + type: node + comment: | + Represents the use of the `&&=` operator on a call. + + foo.bar &&= value + ^^^^^^^^^^^^^^^^^ - name: CallNode fields: - name: receiver @@ -634,50 +665,70 @@ nodes: foo&.bar ^^^^^^^^ - - name: CallOperatorAndWriteNode + - name: CallOperatorWriteNode fields: - - name: target - type: node - kind: CallNode + - name: receiver + type: node? + - name: call_operator_loc + type: location? + - name: message_loc + type: location? + - name: opening_loc + type: location? + - name: arguments + type: node? + kind: ArgumentsNode + - name: closing_loc + type: location? + - name: flags + type: flags + kind: CallNodeFlags + - name: read_name + type: string + - name: write_name + type: string + - name: operator + type: constant - name: operator_loc type: location - name: value type: node comment: | - Represents the use of the `&&=` operator on a call. + Represents the use of an assignment operator on a call. - foo.bar &&= value - ^^^^^^^^^^^^^^^^^ - - name: CallOperatorOrWriteNode + foo.bar += baz + ^^^^^^^^^^^^^^ + - name: CallOrWriteNode fields: - - name: target - type: node - kind: CallNode - - name: value - type: node + - name: receiver + type: node? + - name: call_operator_loc + type: location? + - name: message_loc + type: location? + - name: opening_loc + type: location? + - name: arguments + type: node? + kind: ArgumentsNode + - name: closing_loc + type: location? + - name: flags + type: flags + kind: CallNodeFlags + - name: read_name + type: string + - name: write_name + type: string - name: operator_loc type: location + - name: value + type: node comment: | Represents the use of the `||=` operator on a call. foo.bar ||= value ^^^^^^^^^^^^^^^^^ - - name: CallOperatorWriteNode - fields: - - name: target - type: node - kind: CallNode - - name: operator_loc - type: location - - name: value - type: node - - name: operator - type: constant - comment: | - Represents the use of an assignment operator on a call. - - foo.bar += baz - ^^^^^^^^^^^^^^ - name: CapturePatternNode fields: - name: value diff --git a/yarp/yarp.c b/yarp/yarp.c index 2d609c7922..0587d897ac 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -1451,69 +1451,128 @@ yp_call_node_variable_call_p(yp_call_node_t *node) { return node->base.flags & YP_CALL_NODE_FLAGS_VARIABLE_CALL; } -// Allocate and initialize a new CallOperatorAndWriteNode node. -static yp_call_operator_and_write_node_t * -yp_call_operator_and_write_node_create(yp_parser_t *parser, yp_call_node_t *target, const yp_token_t *operator, yp_node_t *value) { +// Initialize the read name by reading the write name and chopping off the '='. +static void +yp_call_write_read_name_init(yp_string_t *read_name, yp_string_t *write_name) { + size_t length = write_name->length - 1; + + void *memory = malloc(length); + memcpy(memory, write_name->source, length); + + yp_string_owned_init(read_name, (uint8_t *) memory, length); +} + +// Allocate and initialize a new CallAndWriteNode node. +static yp_call_and_write_node_t * +yp_call_and_write_node_create(yp_parser_t *parser, yp_call_node_t *target, const yp_token_t *operator, yp_node_t *value) { + assert(target->block == NULL); assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - yp_call_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_call_operator_and_write_node_t); + yp_call_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_call_and_write_node_t); - *node = (yp_call_operator_and_write_node_t) { + *node = (yp_call_and_write_node_t) { { - .type = YP_NODE_CALL_OPERATOR_AND_WRITE_NODE, + .type = YP_NODE_CALL_AND_WRITE_NODE, + .flags = target->base.flags, .location = { .start = target->base.location.start, .end = value->location.end } }, - .target = target, + .receiver = target->receiver, + .call_operator_loc = target->call_operator_loc, + .message_loc = target->message_loc, + .opening_loc = target->opening_loc, + .arguments = target->arguments, + .closing_loc = target->closing_loc, + .read_name = YP_EMPTY_STRING, + .write_name = target->name, .operator_loc = YP_LOCATION_TOKEN_VALUE(operator), .value = value }; + yp_call_write_read_name_init(&node->read_name, &node->write_name); + + // Here we're going to free the target, since it is no longer necessary. + // However, we don't want to call `yp_node_destroy` because we want to keep + // around all of its children since we just reused them. + free(target); + return node; } // Allocate a new CallOperatorWriteNode node. static yp_call_operator_write_node_t * yp_call_operator_write_node_create(yp_parser_t *parser, yp_call_node_t *target, const yp_token_t *operator, yp_node_t *value) { + assert(target->block == NULL); yp_call_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_call_operator_write_node_t); *node = (yp_call_operator_write_node_t) { { .type = YP_NODE_CALL_OPERATOR_WRITE_NODE, + .flags = target->base.flags, .location = { .start = target->base.location.start, .end = value->location.end } }, - .target = target, + .receiver = target->receiver, + .call_operator_loc = target->call_operator_loc, + .message_loc = target->message_loc, + .opening_loc = target->opening_loc, + .arguments = target->arguments, + .closing_loc = target->closing_loc, + .read_name = YP_EMPTY_STRING, + .write_name = target->name, + .operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1), .operator_loc = YP_LOCATION_TOKEN_VALUE(operator), - .value = value, - .operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1) + .value = value }; + yp_call_write_read_name_init(&node->read_name, &node->write_name); + + // Here we're going to free the target, since it is no longer necessary. + // However, we don't want to call `yp_node_destroy` because we want to keep + // around all of its children since we just reused them. + free(target); + return node; } // Allocate and initialize a new CallOperatorOrWriteNode node. -static yp_call_operator_or_write_node_t * -yp_call_operator_or_write_node_create(yp_parser_t *parser, yp_call_node_t *target, const yp_token_t *operator, yp_node_t *value) { +static yp_call_or_write_node_t * +yp_call_or_write_node_create(yp_parser_t *parser, yp_call_node_t *target, const yp_token_t *operator, yp_node_t *value) { + assert(target->block == NULL); assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL); - yp_call_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_call_operator_or_write_node_t); + yp_call_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_call_or_write_node_t); - *node = (yp_call_operator_or_write_node_t) { + *node = (yp_call_or_write_node_t) { { - .type = YP_NODE_CALL_OPERATOR_OR_WRITE_NODE, + .type = YP_NODE_CALL_OR_WRITE_NODE, + .flags = target->base.flags, .location = { .start = target->base.location.start, .end = value->location.end } }, - .target = target, + .receiver = target->receiver, + .call_operator_loc = target->call_operator_loc, + .message_loc = target->message_loc, + .opening_loc = target->opening_loc, + .arguments = target->arguments, + .closing_loc = target->closing_loc, + .read_name = YP_EMPTY_STRING, + .write_name = target->name, .operator_loc = YP_LOCATION_TOKEN_VALUE(operator), .value = value }; + yp_call_write_read_name_init(&node->read_name, &node->write_name); + + // Here we're going to free the target, since it is no longer necessary. + // However, we don't want to call `yp_node_destroy` because we want to keep + // around all of its children since we just reused them. + free(target); + return node; } @@ -12996,7 +13055,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t node = parse_target(parser, node); yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&="); - return (yp_node_t *) yp_call_operator_and_write_node_create(parser, (yp_call_node_t *) node, &token, value); + return (yp_node_t *) yp_call_and_write_node_create(parser, (yp_call_node_t *) node, &token, value); } case YP_NODE_MULTI_WRITE_NODE: { parser_lex(parser); @@ -13097,7 +13156,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t node = parse_target(parser, node); yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||="); - return (yp_node_t *) yp_call_operator_or_write_node_create(parser, (yp_call_node_t *) node, &token, value); + return (yp_node_t *) yp_call_or_write_node_create(parser, (yp_call_node_t *) node, &token, value); } case YP_NODE_MULTI_WRITE_NODE: { parser_lex(parser); |