Skip to content

Commit 1531433

Browse files
committed
Ensure implicit parameter nodes are destroyed.
When we are about to destroy a node because of a syntax error, we need to check if it is potentially containing an implicit parameter in its subtree.
1 parent d3f99ec commit 1531433

File tree

1 file changed

+37
-28
lines changed

1 file changed

+37
-28
lines changed

src/prism.c

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13454,28 +13454,43 @@ parse_unwriteable_target(pm_parser_t *parser, pm_node_t *target) {
1345413454
return (pm_node_t *) result;
1345513455
}
1345613456

13457+
static bool
13458+
parse_target_implicit_parameter_each(const pm_node_t *node, void *data) {
13459+
switch (PM_NODE_TYPE(node)) {
13460+
case PM_LOCAL_VARIABLE_READ_NODE:
13461+
case PM_IT_LOCAL_VARIABLE_READ_NODE: {
13462+
pm_parser_t *parser = (pm_parser_t *) data;
13463+
pm_node_list_t *implicit_parameters = &parser->current_scope->implicit_parameters;
13464+
13465+
for (size_t index = 0; index < implicit_parameters->size; index++) {
13466+
if (implicit_parameters->nodes[index] == node) {
13467+
// If the node is not the last one in the list, we need to
13468+
// shift the remaining nodes down to fill the gap. This is
13469+
// extremely unlikely to happen.
13470+
if (index != implicit_parameters->size - 1) {
13471+
memmove(&implicit_parameters->nodes[index], &implicit_parameters->nodes[index + 1], (implicit_parameters->size - index - 1) * sizeof(pm_node_t *));
13472+
}
13473+
13474+
implicit_parameters->size--;
13475+
break;
13476+
}
13477+
}
13478+
13479+
return false;
13480+
}
13481+
default:
13482+
return true;
13483+
}
13484+
}
13485+
1345713486
/**
1345813487
* When an implicit local variable is written to or targeted, it becomes a
1345913488
* regular, named local variable. This function removes it from the list of
1346013489
* implicit parameters when that happens.
1346113490
*/
1346213491
static void
13463-
parse_target_implicit_parameter(pm_parser_t *parser, pm_node_t *node) {
13464-
pm_node_list_t *implicit_parameters = &parser->current_scope->implicit_parameters;
13465-
13466-
for (size_t index = 0; index < implicit_parameters->size; index++) {
13467-
if (implicit_parameters->nodes[index] == node) {
13468-
// If the node is not the last one in the list, we need to shift the
13469-
// remaining nodes down to fill the gap. This is extremely unlikely
13470-
// to happen.
13471-
if (index != implicit_parameters->size - 1) {
13472-
memmove(&implicit_parameters->nodes[index], &implicit_parameters->nodes[index + 1], (implicit_parameters->size - index - 1) * sizeof(pm_node_t *));
13473-
}
13474-
13475-
implicit_parameters->size--;
13476-
break;
13477-
}
13478-
}
13492+
parse_target_implicit_parameter(pm_parser_t *parser, const pm_node_t *node) {
13493+
pm_visit_node(node, parse_target_implicit_parameter_each, parser);
1347913494
}
1348013495

1348113496
/**
@@ -13851,18 +13866,12 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
1385113866
// syntax error. In this case we'll fall through to our default
1385213867
// handling. We need to free the value that we parsed because there
1385313868
// is no way for us to attach it to the tree at this point.
13854-
switch (PM_NODE_TYPE(value)) {
13855-
case PM_LOCAL_VARIABLE_READ_NODE:
13856-
case PM_IT_LOCAL_VARIABLE_READ_NODE:
13857-
// Since it is possible for the value to be an implicit
13858-
// parameter, we need to remove it from the list of implicit
13859-
// parameters.
13860-
parse_target_implicit_parameter(parser, value);
13861-
break;
13862-
default:
13863-
break;
13864-
}
13865-
13869+
//
13870+
// Since it is possible for the value to contain an implicit
13871+
// parameter somewhere in its subtree, we need to walk it and remove
13872+
// any implicit parameters from the list of implicit parameters for
13873+
// the current scope.
13874+
parse_target_implicit_parameter(parser, value);
1386613875
pm_node_destroy(parser, value);
1386713876
}
1386813877
PRISM_FALLTHROUGH

0 commit comments

Comments
 (0)