diff --git a/prism/config.yml b/prism/config.yml index f7dcc1f79f..51851bd288 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -673,7 +673,9 @@ flags: - name: FORCED_BINARY_ENCODING comment: "internal bytes forced the encoding to binary" - name: FROZEN - comment: "frozen by virtue of a `frozen_string_literal` comment" + comment: "frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal`" + - name: MUTABLE + comment: "mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal`" comment: Flags for string nodes. - name: SymbolFlags values: diff --git a/prism/extension.c b/prism/extension.c index 9dbebdf6f4..3672ee0dc5 100644 --- a/prism/extension.c +++ b/prism/extension.c @@ -142,7 +142,7 @@ build_options_i(VALUE key, VALUE value, VALUE argument) { } else if (key_id == rb_option_id_offset) { if (!NIL_P(value)) pm_options_offset_set(options, NUM2UINT(value)); } else if (key_id == rb_option_id_frozen_string_literal) { - if (!NIL_P(value)) pm_options_frozen_string_literal_set(options, value == Qtrue); + if (!NIL_P(value)) pm_options_frozen_string_literal_set(options, RTEST(value)); } else if (key_id == rb_option_id_version) { if (!NIL_P(value)) { const char *version = check_string(value); diff --git a/prism/options.c b/prism/options.c index cac6b588eb..1eeae202fb 100644 --- a/prism/options.c +++ b/prism/options.c @@ -37,7 +37,7 @@ pm_options_offset_set(pm_options_t *options, uint32_t offset) { */ PRISM_EXPORTED_FUNCTION void pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_literal) { - options->frozen_string_literal = frozen_string_literal; + options->frozen_string_literal = frozen_string_literal ? 1 : -1; } /** @@ -212,7 +212,7 @@ pm_options_read(pm_options_t *options, const char *data) { data += encoding_length; } - options->frozen_string_literal = (*data++) ? true : false; + options->frozen_string_literal = (int8_t) *data++; options->command_line = (uint8_t) *data++; options->version = (pm_options_version_t) *data++; diff --git a/prism/options.h b/prism/options.h index 17ca2ff8a1..d07f5aa4fa 100644 --- a/prism/options.h +++ b/prism/options.h @@ -13,6 +13,22 @@ #include #include +/** + * String literals should be made frozen. + */ +#define PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED ((int8_t) -1) + +/** + * String literals may be frozen or mutable depending on the implementation + * default. + */ +#define PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET ((int8_t) 0) + +/** + * String literals should be made mutable. + */ +#define PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED ((int8_t) 1) + /** * A scope of locals surrounding the code that is being parsed. */ @@ -85,8 +101,14 @@ typedef struct { /** A bitset of the various options that were set on the command line. */ uint8_t command_line; - /** Whether or not the frozen string literal option has been set. */ - bool frozen_string_literal; + /** + * Whether or not the frozen string literal option has been set. + * May be: + * - PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED + * - PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED + * - PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET + */ + int8_t frozen_string_literal; } pm_options_t; /** diff --git a/prism/parser.h b/prism/parser.h index 7f75bb3cb2..619358c5ba 100644 --- a/prism/parser.h +++ b/prism/parser.h @@ -709,6 +709,16 @@ struct pm_parser { /** The command line flags given from the options. */ uint8_t command_line; + /** + * Whether or not we have found a frozen_string_literal magic comment with + * a true or false value. + * May be: + * - PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED + * - PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED + * - PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET + */ + int8_t frozen_string_literal; + /** Whether or not we're at the beginning of a command. */ bool command_start; @@ -737,12 +747,6 @@ struct pm_parser { */ bool semantic_token_seen; - /** - * Whether or not we have found a frozen_string_literal magic comment with - * a true value. - */ - bool frozen_string_literal; - /** * True if the current regular expression being lexed contains only ASCII * characters. diff --git a/prism/prism.c b/prism/prism.c index 1d94ead82a..99d93eec21 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -5898,8 +5898,13 @@ pm_string_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, pm_string_node_t *node = PM_ALLOC_NODE(parser, pm_string_node_t); pm_node_flags_t flags = 0; - if (parser->frozen_string_literal) { - flags = PM_NODE_FLAG_STATIC_LITERAL | PM_STRING_FLAGS_FROZEN; + switch (parser->frozen_string_literal) { + case PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED: + flags = PM_STRING_FLAGS_MUTABLE; + break; + case PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED: + flags = PM_NODE_FLAG_STATIC_LITERAL | PM_STRING_FLAGS_FROZEN; + break; } *node = (pm_string_node_t) { @@ -6298,8 +6303,13 @@ pm_symbol_node_to_string_node(pm_parser_t *parser, pm_symbol_node_t *node) { pm_string_node_t *new_node = PM_ALLOC_NODE(parser, pm_string_node_t); pm_node_flags_t flags = 0; - if (parser->frozen_string_literal) { - flags = PM_NODE_FLAG_STATIC_LITERAL | PM_STRING_FLAGS_FROZEN; + switch (parser->frozen_string_literal) { + case PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED: + flags = PM_STRING_FLAGS_MUTABLE; + break; + case PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED: + flags = PM_NODE_FLAG_STATIC_LITERAL | PM_STRING_FLAGS_FROZEN; + break; } *new_node = (pm_string_node_t) { @@ -7173,9 +7183,9 @@ parser_lex_magic_comment_encoding(pm_parser_t *parser) { static void parser_lex_magic_comment_frozen_string_literal_value(pm_parser_t *parser, const uint8_t *start, const uint8_t *end) { if ((start + 4 <= end) && pm_strncasecmp(start, (const uint8_t *) "true", 4) == 0) { - parser->frozen_string_literal = true; + parser->frozen_string_literal = 1; } else if ((start + 5 <= end) && pm_strncasecmp(start, (const uint8_t *) "false", 5) == 0) { - parser->frozen_string_literal = false; + parser->frozen_string_literal = -1; } } @@ -18912,7 +18922,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm .in_keyword_arg = false, .current_param_name = 0, .semantic_token_seen = false, - .frozen_string_literal = false, + .frozen_string_literal = 0, .current_regular_expression_ascii_only = false }; @@ -18971,9 +18981,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm } // frozen_string_literal option - if (options->frozen_string_literal) { - parser->frozen_string_literal = true; - } + parser->frozen_string_literal = options->frozen_string_literal; // command_line option parser->command_line = options->command_line;