@@ -12768,6 +12768,65 @@ outer_scope_using_numbered_parameters_p(pm_parser_t *parser) {
12768
12768
return false;
12769
12769
}
12770
12770
12771
+ /**
12772
+ * Parse an identifier into either a local variable read. If the local variable
12773
+ * is not found, it returns NULL instead.
12774
+ */
12775
+ static pm_local_variable_read_node_t *
12776
+ parse_variable(pm_parser_t *parser) {
12777
+ int depth;
12778
+ if ((depth = pm_parser_local_depth(parser, &parser->previous)) != -1) {
12779
+ return pm_local_variable_read_node_create(parser, &parser->previous, (uint32_t) depth);
12780
+ }
12781
+
12782
+ if (!parser->current_scope->closed && pm_token_is_numbered_parameter(parser->previous.start, parser->previous.end)) {
12783
+ // Now that we know we have a numbered parameter, we need to check
12784
+ // if it's allowed in this context. If it is, then we will create a
12785
+ // local variable read. If it's not, then we'll create a normal call
12786
+ // node but add an error.
12787
+ if (parser->current_scope->explicit_params) {
12788
+ pm_parser_err_previous(parser, PM_ERR_NUMBERED_PARAMETER_NOT_ALLOWED);
12789
+ } else if (outer_scope_using_numbered_parameters_p(parser)) {
12790
+ pm_parser_err_previous(parser, PM_ERR_NUMBERED_PARAMETER_OUTER_SCOPE);
12791
+ } else {
12792
+ // Indicate that this scope is using numbered params so that child
12793
+ // scopes cannot.
12794
+ uint8_t number = parser->previous.start[1];
12795
+
12796
+ // We subtract the value for the character '0' to get the actual
12797
+ // integer value of the number (only _1 through _9 are valid)
12798
+ uint8_t numbered_parameters = (uint8_t) (number - '0');
12799
+ if (numbered_parameters > parser->current_scope->numbered_parameters) {
12800
+ parser->current_scope->numbered_parameters = numbered_parameters;
12801
+ pm_parser_numbered_parameters_set(parser, numbered_parameters);
12802
+ }
12803
+
12804
+ // When you use a numbered parameter, it implies the existence
12805
+ // of all of the locals that exist before it. For example,
12806
+ // referencing _2 means that _1 must exist. Therefore here we
12807
+ // loop through all of the possibilities and add them into the
12808
+ // constant pool.
12809
+ uint8_t current = '1';
12810
+ uint8_t *value;
12811
+
12812
+ while (current < number) {
12813
+ value = malloc(2);
12814
+ value[0] = '_';
12815
+ value[1] = current++;
12816
+ pm_parser_local_add_owned(parser, value, 2);
12817
+ }
12818
+
12819
+ // Now we can add the actual token that is being used. For
12820
+ // this one we can add a shared version since it is directly
12821
+ // referenced in the source.
12822
+ pm_parser_local_add_token(parser, &parser->previous);
12823
+ return pm_local_variable_read_node_create(parser, &parser->previous, 0);
12824
+ }
12825
+ }
12826
+
12827
+ return NULL;
12828
+ }
12829
+
12771
12830
/**
12772
12831
* Parse an identifier into either a local variable read or a call.
12773
12832
*/
@@ -12776,56 +12835,8 @@ parse_variable_call(pm_parser_t *parser) {
12776
12835
pm_node_flags_t flags = 0;
12777
12836
12778
12837
if (!match1(parser, PM_TOKEN_PARENTHESIS_LEFT) && (parser->previous.end[-1] != '!') && (parser->previous.end[-1] != '?')) {
12779
- int depth;
12780
- if ((depth = pm_parser_local_depth(parser, &parser->previous)) != -1) {
12781
- return (pm_node_t *) pm_local_variable_read_node_create(parser, &parser->previous, (uint32_t) depth);
12782
- }
12783
-
12784
- if (!parser->current_scope->closed && pm_token_is_numbered_parameter(parser->previous.start, parser->previous.end)) {
12785
- // Now that we know we have a numbered parameter, we need to check
12786
- // if it's allowed in this context. If it is, then we will create a
12787
- // local variable read. If it's not, then we'll create a normal call
12788
- // node but add an error.
12789
- if (parser->current_scope->explicit_params) {
12790
- pm_parser_err_previous(parser, PM_ERR_NUMBERED_PARAMETER_NOT_ALLOWED);
12791
- } else if (outer_scope_using_numbered_parameters_p(parser)) {
12792
- pm_parser_err_previous(parser, PM_ERR_NUMBERED_PARAMETER_OUTER_SCOPE);
12793
- } else {
12794
- // Indicate that this scope is using numbered params so that child
12795
- // scopes cannot.
12796
- uint8_t number = parser->previous.start[1];
12797
-
12798
- // We subtract the value for the character '0' to get the actual
12799
- // integer value of the number (only _1 through _9 are valid)
12800
- uint8_t numbered_parameters = (uint8_t) (number - '0');
12801
- if (numbered_parameters > parser->current_scope->numbered_parameters) {
12802
- parser->current_scope->numbered_parameters = numbered_parameters;
12803
- pm_parser_numbered_parameters_set(parser, numbered_parameters);
12804
- }
12805
-
12806
- // When you use a numbered parameter, it implies the existence
12807
- // of all of the locals that exist before it. For example,
12808
- // referencing _2 means that _1 must exist. Therefore here we
12809
- // loop through all of the possibilities and add them into the
12810
- // constant pool.
12811
- uint8_t current = '1';
12812
- uint8_t *value;
12813
-
12814
- while (current < number) {
12815
- value = malloc(2);
12816
- value[0] = '_';
12817
- value[1] = current++;
12818
- pm_parser_local_add_owned(parser, value, 2);
12819
- }
12820
-
12821
- // Now we can add the actual token that is being used. For
12822
- // this one we can add a shared version since it is directly
12823
- // referenced in the source.
12824
- pm_parser_local_add_token(parser, &parser->previous);
12825
- return (pm_node_t *) pm_local_variable_read_node_create(parser, &parser->previous, 0);
12826
- }
12827
- }
12828
-
12838
+ pm_local_variable_read_node_t *node = parse_variable(parser);
12839
+ if (node != NULL) return (pm_node_t *) node;
12829
12840
flags |= PM_CALL_NODE_FLAGS_VARIABLE_CALL;
12830
12841
}
12831
12842
@@ -13384,15 +13395,12 @@ parse_pattern_primitive(pm_parser_t *parser, pm_diagnostic_id_t diag_id) {
13384
13395
// expression to determine if it's a variable or an expression.
13385
13396
switch (parser->current.type) {
13386
13397
case PM_TOKEN_IDENTIFIER: {
13387
- int depth = pm_parser_local_depth(parser, &parser->current);
13388
-
13389
- if (depth == -1) {
13390
- depth = 0;
13391
- PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_NO_LOCAL_VARIABLE, (int) (parser->current.end - parser->current.start), parser->current.start);
13392
- }
13393
-
13394
- pm_node_t *variable = (pm_node_t *) pm_local_variable_read_node_create(parser, &parser->current, (uint32_t) depth);
13395
13398
parser_lex(parser);
13399
+ pm_node_t *variable = (pm_node_t *) parse_variable(parser);
13400
+ if (variable == NULL) {
13401
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, PM_ERR_NO_LOCAL_VARIABLE, (int) (parser->previous.end - parser->previous.start), parser->previous.start);
13402
+ variable = (pm_node_t *) pm_local_variable_read_node_create(parser, &parser->previous, 0);
13403
+ }
13396
13404
13397
13405
return (pm_node_t *) pm_pinned_variable_node_create(parser, &operator, variable);
13398
13406
}
0 commit comments