summaryrefslogtreecommitdiff
path: root/yarp
diff options
context:
space:
mode:
authorKevin Newton <kddnewton@gmail.com>2023-09-05 14:16:33 -0400
committergit <svn-admin@ruby-lang.org>2023-09-05 19:13:30 +0000
commit767f984017ca264262d9ef04d1db78c6f361e65a (patch)
tree3428a915393cb0fb99d0248fcfce3238f0bc9717 /yarp
parent95e4bdcd6263a8106eac25458a48517aaa4456f8 (diff)
[ruby/yarp] Flatten CallAndWriteNode, CallOrWriteNode, and CallOperatorWriteNode
https://github.com/ruby/yarp/commit/8f26ffa0b2
Diffstat (limited to 'yarp')
-rw-r--r--yarp/config.yml109
-rw-r--r--yarp/yarp.c95
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);