@@ -672,6 +672,122 @@ pm_parser_warn_node(pm_parser_t *parser, const pm_node_t *node, pm_diagnostic_id
672
672
#define PM_PARSER_WARN_NODE_FORMAT(parser, node, diag_id, ...) \
673
673
PM_PARSER_WARN_FORMAT(parser, (node)->location.start, (node)->location.end, diag_id, __VA_ARGS__)
674
674
675
+ /******************************************************************************/
676
+ /* Scope-related functions */
677
+ /******************************************************************************/
678
+
679
+ /**
680
+ * Allocate and initialize a new scope. Push it onto the scope stack.
681
+ */
682
+ static bool
683
+ pm_parser_scope_push(pm_parser_t *parser, bool closed) {
684
+ pm_scope_t *scope = (pm_scope_t *) xmalloc(sizeof(pm_scope_t));
685
+ if (scope == NULL) return false;
686
+
687
+ *scope = (pm_scope_t) {
688
+ .previous = parser->current_scope,
689
+ .locals = { 0 },
690
+ .parameters = PM_SCOPE_PARAMETERS_NONE,
691
+ .numbered_parameters = PM_SCOPE_NUMBERED_PARAMETERS_NONE,
692
+ .shareable_constant = (closed || parser->current_scope == NULL) ? PM_SCOPE_SHAREABLE_CONSTANT_NONE : parser->current_scope->shareable_constant,
693
+ .closed = closed
694
+ };
695
+
696
+ parser->current_scope = scope;
697
+ return true;
698
+ }
699
+
700
+ /**
701
+ * Determine if the current scope is at the top level. This means it is either
702
+ * the top-level scope or it is open to the top-level.
703
+ */
704
+ static bool
705
+ pm_parser_scope_toplevel_p(pm_parser_t *parser) {
706
+ pm_scope_t *scope = parser->current_scope;
707
+
708
+ do {
709
+ if (scope->previous == NULL) return true;
710
+ if (scope->closed) return false;
711
+ } while ((scope = scope->previous) != NULL);
712
+
713
+ assert(false && "unreachable");
714
+ return true;
715
+ }
716
+
717
+ /**
718
+ * Retrieve the scope at the given depth.
719
+ */
720
+ static pm_scope_t *
721
+ pm_parser_scope_find(pm_parser_t *parser, uint32_t depth) {
722
+ pm_scope_t *scope = parser->current_scope;
723
+
724
+ while (depth-- > 0) {
725
+ assert(scope != NULL);
726
+ scope = scope->previous;
727
+ }
728
+
729
+ return scope;
730
+ }
731
+
732
+ static void
733
+ pm_parser_scope_forwarding_param_check(pm_parser_t *parser, const pm_token_t * token, const uint8_t mask, pm_diagnostic_id_t diag) {
734
+ pm_scope_t *scope = parser->current_scope;
735
+ while (scope) {
736
+ if (scope->parameters & mask) {
737
+ if (!scope->closed) {
738
+ pm_parser_err_token(parser, token, diag);
739
+ return;
740
+ }
741
+ return;
742
+ }
743
+ if (scope->closed) break;
744
+ scope = scope->previous;
745
+ }
746
+
747
+ pm_parser_err_token(parser, token, diag);
748
+ }
749
+
750
+ static inline void
751
+ pm_parser_scope_forwarding_block_check(pm_parser_t *parser, const pm_token_t * token) {
752
+ pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_BLOCK, PM_ERR_ARGUMENT_NO_FORWARDING_AMP);
753
+ }
754
+
755
+ static inline void
756
+ pm_parser_scope_forwarding_positionals_check(pm_parser_t *parser, const pm_token_t * token) {
757
+ pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS, PM_ERR_ARGUMENT_NO_FORWARDING_STAR);
758
+ }
759
+
760
+ static inline void
761
+ pm_parser_scope_forwarding_all_check(pm_parser_t *parser, const pm_token_t * token) {
762
+ pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_ALL, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES);
763
+ }
764
+
765
+ static inline void
766
+ pm_parser_scope_forwarding_keywords_check(pm_parser_t *parser, const pm_token_t * token) {
767
+ pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS, PM_ERR_ARGUMENT_NO_FORWARDING_STAR_STAR);
768
+ }
769
+
770
+ /**
771
+ * Get the current state of constant shareability.
772
+ */
773
+ static inline pm_shareable_constant_value_t
774
+ pm_parser_scope_shareable_constant_get(pm_parser_t *parser) {
775
+ return parser->current_scope->shareable_constant;
776
+ }
777
+
778
+ /**
779
+ * Set the current state of constant shareability. We'll set it on all of the
780
+ * open scopes so that reads are quick.
781
+ */
782
+ static void
783
+ pm_parser_scope_shareable_constant_set(pm_parser_t *parser, pm_shareable_constant_value_t shareable_constant) {
784
+ pm_scope_t *scope = parser->current_scope;
785
+
786
+ do {
787
+ scope->shareable_constant = shareable_constant;
788
+ } while (!scope->closed && (scope = scope->previous) != NULL);
789
+ }
790
+
675
791
/******************************************************************************/
676
792
/* Local variable-related functions */
677
793
/******************************************************************************/
@@ -5108,11 +5224,7 @@ pm_local_variable_or_write_node_create(pm_parser_t *parser, pm_node_t *target, c
5108
5224
*/
5109
5225
static pm_local_variable_read_node_t *
5110
5226
pm_local_variable_read_node_create_constant_id(pm_parser_t *parser, const pm_token_t *name, pm_constant_id_t name_id, uint32_t depth, bool missing) {
5111
- if (!missing) {
5112
- pm_scope_t *scope = parser->current_scope;
5113
- for (uint32_t index = 0; index < depth; index++) scope = scope->previous;
5114
- pm_locals_read(&scope->locals, name_id);
5115
- }
5227
+ if (!missing) pm_locals_read(&pm_parser_scope_find(parser, depth)->locals, name_id);
5116
5228
5117
5229
pm_local_variable_read_node_t *node = PM_ALLOC_NODE(parser, pm_local_variable_read_node_t);
5118
5230
@@ -7181,107 +7293,6 @@ pm_yield_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_lo
7181
7293
7182
7294
#undef PM_ALLOC_NODE
7183
7295
7184
- /******************************************************************************/
7185
- /* Scope-related functions */
7186
- /******************************************************************************/
7187
-
7188
- /**
7189
- * Allocate and initialize a new scope. Push it onto the scope stack.
7190
- */
7191
- static bool
7192
- pm_parser_scope_push(pm_parser_t *parser, bool closed) {
7193
- pm_scope_t *scope = (pm_scope_t *) xmalloc(sizeof(pm_scope_t));
7194
- if (scope == NULL) return false;
7195
-
7196
- *scope = (pm_scope_t) {
7197
- .previous = parser->current_scope,
7198
- .locals = { 0 },
7199
- .parameters = PM_SCOPE_PARAMETERS_NONE,
7200
- .numbered_parameters = PM_SCOPE_NUMBERED_PARAMETERS_NONE,
7201
- .shareable_constant = (closed || parser->current_scope == NULL) ? PM_SCOPE_SHAREABLE_CONSTANT_NONE : parser->current_scope->shareable_constant,
7202
- .closed = closed
7203
- };
7204
-
7205
- parser->current_scope = scope;
7206
- return true;
7207
- }
7208
-
7209
- /**
7210
- * Determine if the current scope is at the top level. This means it is either
7211
- * the top-level scope or it is open to the top-level.
7212
- */
7213
- static bool
7214
- pm_parser_scope_toplevel_p(pm_parser_t *parser) {
7215
- pm_scope_t *scope = parser->current_scope;
7216
-
7217
- do {
7218
- if (scope->previous == NULL) return true;
7219
- if (scope->closed) return false;
7220
- } while ((scope = scope->previous) != NULL);
7221
-
7222
- assert(false && "unreachable");
7223
- return true;
7224
- }
7225
-
7226
- static void
7227
- pm_parser_scope_forwarding_param_check(pm_parser_t *parser, const pm_token_t * token, const uint8_t mask, pm_diagnostic_id_t diag) {
7228
- pm_scope_t *scope = parser->current_scope;
7229
- while (scope) {
7230
- if (scope->parameters & mask) {
7231
- if (!scope->closed) {
7232
- pm_parser_err_token(parser, token, diag);
7233
- return;
7234
- }
7235
- return;
7236
- }
7237
- if (scope->closed) break;
7238
- scope = scope->previous;
7239
- }
7240
-
7241
- pm_parser_err_token(parser, token, diag);
7242
- }
7243
-
7244
- static inline void
7245
- pm_parser_scope_forwarding_block_check(pm_parser_t *parser, const pm_token_t * token) {
7246
- pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_BLOCK, PM_ERR_ARGUMENT_NO_FORWARDING_AMP);
7247
- }
7248
-
7249
- static inline void
7250
- pm_parser_scope_forwarding_positionals_check(pm_parser_t *parser, const pm_token_t * token) {
7251
- pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS, PM_ERR_ARGUMENT_NO_FORWARDING_STAR);
7252
- }
7253
-
7254
- static inline void
7255
- pm_parser_scope_forwarding_all_check(pm_parser_t *parser, const pm_token_t * token) {
7256
- pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_ALL, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES);
7257
- }
7258
-
7259
- static inline void
7260
- pm_parser_scope_forwarding_keywords_check(pm_parser_t *parser, const pm_token_t * token) {
7261
- pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS, PM_ERR_ARGUMENT_NO_FORWARDING_STAR_STAR);
7262
- }
7263
-
7264
- /**
7265
- * Get the current state of constant shareability.
7266
- */
7267
- static inline pm_shareable_constant_value_t
7268
- pm_parser_scope_shareable_constant_get(pm_parser_t *parser) {
7269
- return parser->current_scope->shareable_constant;
7270
- }
7271
-
7272
- /**
7273
- * Set the current state of constant shareability. We'll set it on all of the
7274
- * open scopes so that reads are quick.
7275
- */
7276
- static void
7277
- pm_parser_scope_shareable_constant_set(pm_parser_t *parser, pm_shareable_constant_value_t shareable_constant) {
7278
- pm_scope_t *scope = parser->current_scope;
7279
-
7280
- do {
7281
- scope->shareable_constant = shareable_constant;
7282
- } while (!scope->closed && (scope = scope->previous) != NULL);
7283
- }
7284
-
7285
7296
/**
7286
7297
* Check if any of the currently visible scopes contain a local variable
7287
7298
* described by the given constant id.
@@ -12470,10 +12481,7 @@ parse_target(pm_parser_t *parser, pm_node_t *target) {
12470
12481
const pm_local_variable_read_node_t *cast = (const pm_local_variable_read_node_t *) target;
12471
12482
uint32_t name = cast->name;
12472
12483
uint32_t depth = cast->depth;
12473
-
12474
- pm_scope_t *scope = parser->current_scope;
12475
- for (uint32_t index = 0; index < depth; index++) scope = scope->previous;
12476
- pm_locals_unread(&scope->locals, name);
12484
+ pm_locals_unread(&pm_parser_scope_find(parser, depth)->locals, name);
12477
12485
12478
12486
assert(sizeof(pm_local_variable_target_node_t) == sizeof(pm_local_variable_read_node_t));
12479
12487
target->type = PM_LOCAL_VARIABLE_TARGET_NODE;
@@ -12624,17 +12632,14 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
12624
12632
pm_refute_numbered_parameter(parser, target->location.start, target->location.end);
12625
12633
pm_local_variable_read_node_t *local_read = (pm_local_variable_read_node_t *) target;
12626
12634
12627
- pm_constant_id_t constant_id = local_read->name;
12635
+ pm_constant_id_t name = local_read->name;
12628
12636
uint32_t depth = local_read->depth;
12629
-
12630
- pm_scope_t *scope = parser->current_scope;
12631
- for (uint32_t index = 0; index < depth; index++) scope = scope->previous;
12632
- pm_locals_unread(&scope->locals, constant_id);
12637
+ pm_locals_unread(&pm_parser_scope_find(parser, depth)->locals, name);
12633
12638
12634
12639
pm_location_t name_loc = target->location;
12635
12640
pm_node_destroy(parser, target);
12636
12641
12637
- return (pm_node_t *) pm_local_variable_write_node_create(parser, constant_id , depth, value, &name_loc, operator);
12642
+ return (pm_node_t *) pm_local_variable_write_node_create(parser, name , depth, value, &name_loc, operator);
12638
12643
}
12639
12644
case PM_INSTANCE_VARIABLE_READ_NODE: {
12640
12645
pm_node_t *write_node = (pm_node_t *) pm_instance_variable_write_node_create(parser, (pm_instance_variable_read_node_t *) target, operator, value);
0 commit comments