[ruby/prism] Change frozen_string_literal to be a tri-state

An explicit `false` is not equivalent to the comment being missing,
because the default can be switched with a runtime flag:

```bash
$ ruby --enable-frozen-string-literal -e 'p "foo".frozen?'
true
```

https://github.com/ruby/prism/commit/4660f58775
This commit is contained in:
Jean Boussier 2024-03-12 12:17:55 +01:00 committed by git
parent 0f076fa520
commit 53a77d9b90
6 changed files with 58 additions and 22 deletions

View File

@ -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:

View File

@ -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);

View File

@ -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++;

View File

@ -13,6 +13,22 @@
#include <stddef.h>
#include <stdint.h>
/**
* 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;
/**

View File

@ -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.

View File

@ -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;