Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions include/prism/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,20 @@ typedef void (*pm_options_shebang_callback_t)(struct pm_options *options, const
* parse in the same way as a specific version of CRuby would have.
*/
typedef enum {
/** The current version of prism. */
PM_OPTIONS_VERSION_LATEST = 0,
/** If an explicit version is not provided, the current version of prism will be used. */
PM_OPTIONS_VERSION_UNSET = 0,

/** The vendored version of prism in CRuby 3.3.x. */
PM_OPTIONS_VERSION_CRUBY_3_3 = 1,

/** The vendored version of prism in CRuby 3.4.x. */
PM_OPTIONS_VERSION_CRUBY_3_4 = 2
PM_OPTIONS_VERSION_CRUBY_3_4 = 2,

/** The vendored version of prism in CRuby 3.5.x. */
PM_OPTIONS_VERSION_CRUBY_3_5 = 3,

/** The current version of prism. */
PM_OPTIONS_VERSION_LATEST = PM_OPTIONS_VERSION_CRUBY_3_5
} pm_options_version_t;

/**
Expand Down
5 changes: 3 additions & 2 deletions java/org/prism/ParsingOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ public abstract class ParsingOptions {
* See pm_options_version_t in include/prism/options.h.
*/
public enum SyntaxVersion {
LATEST(0),
LATEST(0), // Handled in pm_parser_init
V3_3(1),
V3_4(2);
V3_4(2),
V3_5(3);

private final int value;

Expand Down
6 changes: 4 additions & 2 deletions javascript/src/parsePrism.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,14 @@ function dumpOptions(options) {
values.push(dumpCommandLineOptions(options));

template.push("C");
if (!options.version || options.version === "latest" || options.version.match(/^3\.5(\.\d+)?$/)) {
values.push(0);
if (!options.version || options.version === "latest") {
values.push(0); // Handled in pm_parser_init
} else if (options.version.match(/^3\.3(\.\d+)?$/)) {
values.push(1);
} else if (options.version.match(/^3\.4(\.\d+)?$/)) {
values.push(2);
} else if (options.version.match(/^3\.5(\.\d+)?$/)) {
values.push(3);
} else {
throw new Error(`Unsupported version '${options.version}' in compiler options`);
}
Expand Down
4 changes: 2 additions & 2 deletions lib/prism/ffi.rb
Original file line number Diff line number Diff line change
Expand Up @@ -422,13 +422,13 @@ def dump_options_command_line(options)
def dump_options_version(version)
case version
when nil, "latest"
0
0 # Handled in pm_parser_init
when /\A3\.3(\.\d+)?\z/
1
when /\A3\.4(\.\d+)?\z/
2
when /\A3\.5(\.\d+)?\z/
0
3
else
raise ArgumentError, "invalid version: #{version}"
end
Expand Down
4 changes: 2 additions & 2 deletions src/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ pm_options_version_set(pm_options_t *options, const char *version, size_t length
}

if (strncmp(version, "3.5", 3) == 0) {
options->version = PM_OPTIONS_VERSION_LATEST;
options->version = PM_OPTIONS_VERSION_CRUBY_3_5;
return true;
}

Expand All @@ -108,7 +108,7 @@ pm_options_version_set(pm_options_t *options, const char *version, size_t length
}

if (strncmp(version, "3.5.", 4) == 0 && is_number(version + 4, length - 4)) {
options->version = PM_OPTIONS_VERSION_LATEST;
options->version = PM_OPTIONS_VERSION_CRUBY_3_5;
return true;
}
}
Expand Down
26 changes: 16 additions & 10 deletions src/prism.c
Original file line number Diff line number Diff line change
Expand Up @@ -1409,7 +1409,7 @@ pm_conditional_predicate_warn_write_literal_p(const pm_node_t *node) {
static inline void
pm_conditional_predicate_warn_write_literal(pm_parser_t *parser, const pm_node_t *node) {
if (pm_conditional_predicate_warn_write_literal_p(node)) {
pm_parser_warn_node(parser, node, parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_WARN_EQUAL_IN_CONDITIONAL_3_3 : PM_WARN_EQUAL_IN_CONDITIONAL);
pm_parser_warn_node(parser, node, parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_WARN_EQUAL_IN_CONDITIONAL_3_3 : PM_WARN_EQUAL_IN_CONDITIONAL);
}
}

Expand Down Expand Up @@ -2976,7 +2976,7 @@ pm_call_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const
*/
static void
pm_index_arguments_check(pm_parser_t *parser, const pm_arguments_node_t *arguments, const pm_node_t *block) {
if (parser->version != PM_OPTIONS_VERSION_CRUBY_3_3) {
if (parser->version >= PM_OPTIONS_VERSION_CRUBY_3_4) {
if (arguments != NULL && PM_NODE_FLAG_P(arguments, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS)) {
pm_node_t *node;
PM_NODE_LIST_FOREACH(&arguments->arguments, index, node) {
Expand Down Expand Up @@ -9094,7 +9094,7 @@ lex_global_variable(pm_parser_t *parser) {
} while ((width = char_is_identifier(parser, parser->current.end, parser->end - parser->current.end)) > 0);

// $0 isn't allowed to be followed by anything.
pm_diagnostic_id_t diag_id = parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_ERR_INVALID_VARIABLE_GLOBAL_3_3 : PM_ERR_INVALID_VARIABLE_GLOBAL;
pm_diagnostic_id_t diag_id = parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_ERR_INVALID_VARIABLE_GLOBAL_3_3 : PM_ERR_INVALID_VARIABLE_GLOBAL;
PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, parser->current, diag_id);
}

Expand Down Expand Up @@ -9131,7 +9131,7 @@ lex_global_variable(pm_parser_t *parser) {
} else {
// If we get here, then we have a $ followed by something that
// isn't recognized as a global variable.
pm_diagnostic_id_t diag_id = parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_ERR_INVALID_VARIABLE_GLOBAL_3_3 : PM_ERR_INVALID_VARIABLE_GLOBAL;
pm_diagnostic_id_t diag_id = parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_ERR_INVALID_VARIABLE_GLOBAL_3_3 : PM_ERR_INVALID_VARIABLE_GLOBAL;
const uint8_t *end = parser->current.end + parser->encoding->char_width(parser->current.end, parser->end - parser->current.end);
PM_PARSER_ERR_FORMAT(parser, parser->current.start, end, diag_id, (int) (end - parser->current.start), (const char *) parser->current.start);
}
Expand Down Expand Up @@ -10158,7 +10158,7 @@ lex_at_variable(pm_parser_t *parser) {
}
} else if (parser->current.end < end && pm_char_is_decimal_digit(*parser->current.end)) {
pm_diagnostic_id_t diag_id = (type == PM_TOKEN_CLASS_VARIABLE) ? PM_ERR_INCOMPLETE_VARIABLE_CLASS : PM_ERR_INCOMPLETE_VARIABLE_INSTANCE;
if (parser->version == PM_OPTIONS_VERSION_CRUBY_3_3) {
if (parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3) {
diag_id = (type == PM_TOKEN_CLASS_VARIABLE) ? PM_ERR_INCOMPLETE_VARIABLE_CLASS_3_3 : PM_ERR_INCOMPLETE_VARIABLE_INSTANCE_3_3;
}

Expand Down Expand Up @@ -14648,7 +14648,7 @@ parse_parameters(
parser_lex(parser);

pm_constant_id_t name_id = pm_parser_constant_id_token(parser, &name);
uint32_t reads = parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? pm_locals_reads(&parser->current_scope->locals, name_id) : 0;
uint32_t reads = parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 ? pm_locals_reads(&parser->current_scope->locals, name_id) : 0;

if (accepts_blocks_in_defaults) pm_accepts_block_stack_push(parser, true);
pm_node_t *value = parse_value_expression(parser, binding_power, false, false, PM_ERR_PARAMETER_NO_DEFAULT, (uint16_t) (depth + 1));
Expand All @@ -14664,7 +14664,7 @@ parse_parameters(
// If the value of the parameter increased the number of
// reads of that parameter, then we need to warn that we
// have a circular definition.
if ((parser->version == PM_OPTIONS_VERSION_CRUBY_3_3) && (pm_locals_reads(&parser->current_scope->locals, name_id) != reads)) {
if ((parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3) && (pm_locals_reads(&parser->current_scope->locals, name_id) != reads)) {
PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, name, PM_ERR_PARAMETER_CIRCULAR);
}

Expand Down Expand Up @@ -14749,13 +14749,13 @@ parse_parameters(

if (token_begins_expression_p(parser->current.type)) {
pm_constant_id_t name_id = pm_parser_constant_id_token(parser, &local);
uint32_t reads = parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? pm_locals_reads(&parser->current_scope->locals, name_id) : 0;
uint32_t reads = parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 ? pm_locals_reads(&parser->current_scope->locals, name_id) : 0;

if (accepts_blocks_in_defaults) pm_accepts_block_stack_push(parser, true);
pm_node_t *value = parse_value_expression(parser, binding_power, false, false, PM_ERR_PARAMETER_NO_DEFAULT_KW, (uint16_t) (depth + 1));
if (accepts_blocks_in_defaults) pm_accepts_block_stack_pop(parser);

if (parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 && (pm_locals_reads(&parser->current_scope->locals, name_id) != reads)) {
if (parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 && (pm_locals_reads(&parser->current_scope->locals, name_id) != reads)) {
PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, local, PM_ERR_PARAMETER_CIRCULAR);
}

Expand Down Expand Up @@ -16459,7 +16459,7 @@ parse_variable(pm_parser_t *parser) {
pm_node_list_append(&current_scope->implicit_parameters, node);

return node;
} else if ((parser->version != PM_OPTIONS_VERSION_CRUBY_3_3) && pm_token_is_it(parser->previous.start, parser->previous.end)) {
} else if ((parser->version >= PM_OPTIONS_VERSION_CRUBY_3_4) && pm_token_is_it(parser->previous.start, parser->previous.end)) {
pm_node_t *node = (pm_node_t *) pm_it_local_variable_read_node_create(parser, &parser->previous);
pm_node_list_append(&current_scope->implicit_parameters, node);

Expand Down Expand Up @@ -22628,6 +22628,12 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
}
}

// Now that we have established the user-provided options, check if
// a version was given and parse as the latest version otherwise.
if (parser->version == PM_OPTIONS_VERSION_UNSET) {
parser->version = PM_OPTIONS_VERSION_LATEST;
}

pm_accepts_block_stack_push(parser, true);

// Skip past the UTF-8 BOM if it exists.
Expand Down
Loading