@@ -5731,6 +5731,25 @@ pm_self_node_create(pm_parser_t *parser, const pm_token_t *token) {
5731
5731
return node;
5732
5732
}
5733
5733
5734
+ /**
5735
+ * Allocate and initialize a new ShareableConstantNode node.
5736
+ */
5737
+ static pm_shareable_constant_node_t *
5738
+ pm_shareable_constant_node_create(pm_parser_t *parser, pm_node_t *write, pm_shareable_constant_value_t value) {
5739
+ pm_shareable_constant_node_t *node = PM_ALLOC_NODE(parser, pm_shareable_constant_node_t);
5740
+
5741
+ *node = (pm_shareable_constant_node_t) {
5742
+ {
5743
+ .type = PM_SHAREABLE_CONSTANT_NODE,
5744
+ .flags = (pm_node_flags_t) value,
5745
+ .location = PM_LOCATION_NODE_VALUE(write)
5746
+ },
5747
+ .write = write
5748
+ };
5749
+
5750
+ return node;
5751
+ }
5752
+
5734
5753
/**
5735
5754
* Allocate a new SingletonClassNode node.
5736
5755
*/
@@ -6745,6 +6764,7 @@ pm_parser_scope_push(pm_parser_t *parser, bool closed) {
6745
6764
.locals = { 0 },
6746
6765
.parameters = PM_SCOPE_PARAMETERS_NONE,
6747
6766
.numbered_parameters = PM_SCOPE_NUMBERED_PARAMETERS_NONE,
6767
+ .shareable_constant = (closed || parser->current_scope == NULL) ? PM_SCOPE_SHAREABLE_CONSTANT_NONE : parser->current_scope->shareable_constant,
6748
6768
.closed = closed
6749
6769
};
6750
6770
@@ -6790,6 +6810,27 @@ pm_parser_scope_forwarding_keywords_check(pm_parser_t *parser, const pm_token_t
6790
6810
pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH);
6791
6811
}
6792
6812
6813
+ /**
6814
+ * Get the current state of constant shareability.
6815
+ */
6816
+ static inline pm_shareable_constant_value_t
6817
+ pm_parser_scope_shareable_constant_get(pm_parser_t *parser) {
6818
+ return parser->current_scope->shareable_constant;
6819
+ }
6820
+
6821
+ /**
6822
+ * Set the current state of constant shareability. We'll set it on all of the
6823
+ * open scopes so that reads are quick.
6824
+ */
6825
+ static void
6826
+ pm_parser_scope_shareable_constant_set(pm_parser_t *parser, pm_shareable_constant_value_t shareable_constant) {
6827
+ pm_scope_t *scope = parser->current_scope;
6828
+
6829
+ do {
6830
+ scope->shareable_constant = shareable_constant;
6831
+ } while (!scope->closed && (scope = scope->previous) != NULL);
6832
+ }
6833
+
6793
6834
/**
6794
6835
* Save the current param name as the return value and set it to the given
6795
6836
* constant id.
@@ -7345,6 +7386,28 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) {
7345
7386
}
7346
7387
}
7347
7388
7389
+ // If we have hit a ractor pragma, attempt to lex that.
7390
+ uint32_t value_length = (uint32_t) (value_end - value_start);
7391
+ if (key_length == 24 && pm_strncasecmp(key_source, (const uint8_t *) "shareable_constant_value", 24) == 0) {
7392
+ if (value_length == 4 && pm_strncasecmp(value_start, (const uint8_t *) "none", 4) == 0) {
7393
+ pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_NONE);
7394
+ } else if (value_length == 7 && pm_strncasecmp(value_start, (const uint8_t *) "literal", 7) == 0) {
7395
+ pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_LITERAL);
7396
+ } else if (value_length == 23 && pm_strncasecmp(value_start, (const uint8_t *) "experimental_everything", 23) == 0) {
7397
+ pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_EVERYTHING);
7398
+ } else if (value_length == 17 && pm_strncasecmp(value_start, (const uint8_t *) "experimental_copy", 17) == 0) {
7399
+ pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_COPY);
7400
+ } else {
7401
+ PM_PARSER_WARN_TOKEN_FORMAT(
7402
+ parser,
7403
+ parser->current,
7404
+ PM_WARN_INVALID_SHAREABLE_CONSTANT_VALUE,
7405
+ (int) value_length,
7406
+ (const char *) value_start
7407
+ );
7408
+ }
7409
+ }
7410
+
7348
7411
// When we're done, we want to free the string in case we had to
7349
7412
// allocate memory for it.
7350
7413
pm_string_free(&key);
@@ -11991,6 +12054,21 @@ parse_target_validate(pm_parser_t *parser, pm_node_t *target) {
11991
12054
return result;
11992
12055
}
11993
12056
12057
+ /**
12058
+ * Potentially wrap a constant write node in a shareable constant node depending
12059
+ * on the current state.
12060
+ */
12061
+ static pm_node_t *
12062
+ parse_shareable_constant_write(pm_parser_t *parser, pm_node_t *write) {
12063
+ pm_shareable_constant_value_t shareable_constant = pm_parser_scope_shareable_constant_get(parser);
12064
+
12065
+ if (shareable_constant != PM_SCOPE_SHAREABLE_CONSTANT_NONE) {
12066
+ return (pm_node_t *) pm_shareable_constant_node_create(parser, write, shareable_constant);
12067
+ }
12068
+
12069
+ return write;
12070
+ }
12071
+
11994
12072
/**
11995
12073
* Convert the given node into a valid write node.
11996
12074
*/
@@ -12005,15 +12083,17 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
12005
12083
pm_node_destroy(parser, target);
12006
12084
return (pm_node_t *) node;
12007
12085
}
12008
- case PM_CONSTANT_PATH_NODE:
12009
- return (pm_node_t *) pm_constant_path_write_node_create(parser, (pm_constant_path_node_t *) target, operator, value);
12086
+ case PM_CONSTANT_PATH_NODE: {
12087
+ pm_node_t *node = (pm_node_t *) pm_constant_path_write_node_create(parser, (pm_constant_path_node_t *) target, operator, value);
12088
+ return parse_shareable_constant_write(parser, node);
12089
+ }
12010
12090
case PM_CONSTANT_READ_NODE: {
12011
- pm_constant_write_node_t *node = pm_constant_write_node_create(parser, (pm_constant_read_node_t *) target, operator, value);
12091
+ pm_node_t *node = (pm_node_t *) pm_constant_write_node_create(parser, (pm_constant_read_node_t *) target, operator, value);
12012
12092
if (context_def_p(parser)) {
12013
- pm_parser_err_node(parser, (pm_node_t *) node, PM_ERR_WRITE_TARGET_IN_METHOD);
12093
+ pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_IN_METHOD);
12014
12094
}
12015
12095
pm_node_destroy(parser, target);
12016
- return (pm_node_t *) node;
12096
+ return parse_shareable_constant_write(parser, node) ;
12017
12097
}
12018
12098
case PM_BACK_REFERENCE_READ_NODE:
12019
12099
case PM_NUMBERED_REFERENCE_READ_NODE:
@@ -17954,16 +18034,18 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
17954
18034
parser_lex(parser);
17955
18035
17956
18036
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
17957
- return (pm_node_t *) pm_constant_path_and_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value);
18037
+ pm_node_t *write = (pm_node_t *) pm_constant_path_and_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value);
18038
+
18039
+ return parse_shareable_constant_write(parser, write);
17958
18040
}
17959
18041
case PM_CONSTANT_READ_NODE: {
17960
18042
parser_lex(parser);
17961
18043
17962
18044
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
17963
- pm_node_t *result = (pm_node_t *) pm_constant_and_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value);
18045
+ pm_node_t *write = (pm_node_t *) pm_constant_and_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value);
17964
18046
17965
18047
pm_node_destroy(parser, node);
17966
- return result ;
18048
+ return parse_shareable_constant_write(parser, write) ;
17967
18049
}
17968
18050
case PM_INSTANCE_VARIABLE_READ_NODE: {
17969
18051
parser_lex(parser);
@@ -18065,16 +18147,18 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
18065
18147
parser_lex(parser);
18066
18148
18067
18149
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
18068
- return (pm_node_t *) pm_constant_path_or_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value);
18150
+ pm_node_t *write = (pm_node_t *) pm_constant_path_or_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value);
18151
+
18152
+ return parse_shareable_constant_write(parser, write);
18069
18153
}
18070
18154
case PM_CONSTANT_READ_NODE: {
18071
18155
parser_lex(parser);
18072
18156
18073
18157
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
18074
- pm_node_t *result = (pm_node_t *) pm_constant_or_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value);
18158
+ pm_node_t *write = (pm_node_t *) pm_constant_or_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value);
18075
18159
18076
18160
pm_node_destroy(parser, node);
18077
- return result ;
18161
+ return parse_shareable_constant_write(parser, write) ;
18078
18162
}
18079
18163
case PM_INSTANCE_VARIABLE_READ_NODE: {
18080
18164
parser_lex(parser);
@@ -18186,16 +18270,18 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
18186
18270
parser_lex(parser);
18187
18271
18188
18272
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
18189
- return (pm_node_t *) pm_constant_path_operator_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value);
18273
+ pm_node_t *write = (pm_node_t *) pm_constant_path_operator_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value);
18274
+
18275
+ return parse_shareable_constant_write(parser, write);
18190
18276
}
18191
18277
case PM_CONSTANT_READ_NODE: {
18192
18278
parser_lex(parser);
18193
18279
18194
18280
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
18195
- pm_node_t *result = (pm_node_t *) pm_constant_operator_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value);
18281
+ pm_node_t *write = (pm_node_t *) pm_constant_operator_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value);
18196
18282
18197
18283
pm_node_destroy(parser, node);
18198
- return result ;
18284
+ return parse_shareable_constant_write(parser, write) ;
18199
18285
}
18200
18286
case PM_INSTANCE_VARIABLE_READ_NODE: {
18201
18287
parser_lex(parser);
0 commit comments