Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PRISM] Use new CLI options #10145

Merged
merged 2 commits into from
Feb 29, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 19 additions & 10 deletions lib/prism/ffi.rb
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,24 @@ def parse_file_success_common(string, options) # :nodoc:
LibRubyParser.pm_parse_success_p(string.pointer, string.length, dump_options(options))
end

# Return the value that should be dumped for the command_line option.
def dump_options_command_line(options)
command_line = options.fetch(:command_line, "")
raise ArgumentError, "command_line must be a string" unless command_line.is_a?(String)

command_line.each_char.inject(0) do |value, char|
case char
when "a" then value | 0b000001
when "e" then value | 0b000010
when "l" then value | 0b000100
when "n" then value | 0b001000
when "p" then value | 0b010000
when "x" then value | 0b100000
else raise ArgumentError, "invalid command_line option: #{char}"
end
end
end

# Convert the given options into a serialized options string.
def dump_options(options)
template = +""
Expand Down Expand Up @@ -343,16 +361,7 @@ def dump_options(options)
values << (options.fetch(:frozen_string_literal, false) ? 1 : 0)

template << "C"
values << (options.fetch(:command_line_p, false) ? 1 : 0)

template << "C"
values << (options.fetch(:command_line_n, false) ? 1 : 0)

template << "C"
values << (options.fetch(:command_line_l, false) ? 1 : 0)

template << "C"
values << (options.fetch(:command_line_a, false) ? 1 : 0)
values << dump_options_command_line(options)

template << "C"
values << { nil => 0, "3.3.0" => 1, "3.4.0" => 0, "latest" => 0 }.fetch(options[:version])
Expand Down
63 changes: 36 additions & 27 deletions prism/extension.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@ ID rb_option_id_line;
ID rb_option_id_frozen_string_literal;
ID rb_option_id_version;
ID rb_option_id_scopes;
ID rb_option_id_command_line_p;
ID rb_option_id_command_line_n;
ID rb_option_id_command_line_l;
ID rb_option_id_command_line_a;
ID rb_option_id_command_line;

/******************************************************************************/
/* IO of Ruby code */
Expand Down Expand Up @@ -148,21 +145,32 @@ build_options_i(VALUE key, VALUE value, VALUE argument) {
const char *version = check_string(value);

if (!pm_options_version_set(options, version, RSTRING_LEN(value))) {
rb_raise(rb_eArgError, "invalid version: %"PRIsVALUE, value);
rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value);
}
}
} else if (key_id == rb_option_id_scopes) {
if (!NIL_P(value)) build_options_scopes(options, value);
} else if (key_id == rb_option_id_command_line_p) {
if (!NIL_P(value)) pm_options_command_line_p_set(options, value == Qtrue);
} else if (key_id == rb_option_id_command_line_n) {
if (!NIL_P(value)) pm_options_command_line_n_set(options, value == Qtrue);
} else if (key_id == rb_option_id_command_line_l) {
if (!NIL_P(value)) pm_options_command_line_l_set(options, value == Qtrue);
} else if (key_id == rb_option_id_command_line_a) {
if (!NIL_P(value)) pm_options_command_line_a_set(options, value == Qtrue);
} else if (key_id == rb_option_id_command_line) {
if (!NIL_P(value)) {
const char *string = check_string(value);
uint8_t command_line = 0;

for (size_t index = 0; index < strlen(string); index++) {
switch (string[index]) {
case 'a': command_line |= PM_OPTIONS_COMMAND_LINE_A; break;
case 'e': command_line |= PM_OPTIONS_COMMAND_LINE_E; break;
case 'l': command_line |= PM_OPTIONS_COMMAND_LINE_L; break;
case 'n': command_line |= PM_OPTIONS_COMMAND_LINE_N; break;
case 'p': command_line |= PM_OPTIONS_COMMAND_LINE_P; break;
case 'x': command_line |= PM_OPTIONS_COMMAND_LINE_X; break;
default: rb_raise(rb_eArgError, "invalid command line flag: '%c'", string[index]); break;
}
}

pm_options_command_line_set(options, command_line);
}
} else {
rb_raise(rb_eArgError, "unknown keyword: %"PRIsVALUE, key);
rb_raise(rb_eArgError, "unknown keyword: %" PRIsVALUE, key);
}

return ST_CONTINUE;
Expand Down Expand Up @@ -697,21 +705,25 @@ parse_input(pm_string_t *input, const pm_options_t *options) {
* Parse the given string and return a ParseResult instance. The options that
* are supported are:
*
* * `filepath` - the filepath of the source being parsed. This should be a
* string or nil
* * `command_line` - either nil or a string of the various options that were
* set on the command line. Valid values are combinations of "a", "l",
* "n", "p", and "x".
* * `encoding` - the encoding of the source being parsed. This should be an
* encoding or nil
* * `line` - the line number that the parse starts on. This should be an
* integer or nil. Note that this is 1-indexed.
* encoding or nil.
* * `filepath` - the filepath of the source being parsed. This should be a
* string or nil.
* * `frozen_string_literal` - whether or not the frozen string literal pragma
* has been set. This should be a boolean or nil.
* * `version` - the version of prism that should be used to parse Ruby code. By
* default prism assumes you want to parse with the latest vesion of
* prism (which you can trigger with `nil` or `"latest"`). If you want to
* parse exactly as CRuby 3.3.0 would, then you can pass `"3.3.0"`.
* * `line` - the line number that the parse starts on. This should be an
* integer or nil. Note that this is 1-indexed.
* * `scopes` - the locals that are in scope surrounding the code that is being
* parsed. This should be an array of arrays of symbols or nil. Scopes are
* ordered from the outermost scope to the innermost one.
* * `version` - the version of Ruby syntax that prism should used to parse Ruby
* code. By default prism assumes you want to parse with the latest vesion
* of Ruby syntax (which you can trigger with `nil` or `"latest"`). You
* may also restrict the syntax to a specific version of Ruby. The
* supported values are `"3.3.0"` and `"3.4.0"`.
*/
static VALUE
parse(int argc, VALUE *argv, VALUE self) {
Expand Down Expand Up @@ -1244,10 +1256,7 @@ Init_prism(void) {
rb_option_id_frozen_string_literal = rb_intern_const("frozen_string_literal");
rb_option_id_version = rb_intern_const("version");
rb_option_id_scopes = rb_intern_const("scopes");
rb_option_id_command_line_p = rb_intern_const("command_line_p");
rb_option_id_command_line_n = rb_intern_const("command_line_n");
rb_option_id_command_line_l = rb_intern_const("command_line_l");
rb_option_id_command_line_a = rb_intern_const("command_line_a");
rb_option_id_command_line = rb_intern_const("command_line");

/**
* The version of the prism library.
Expand Down
35 changes: 4 additions & 31 deletions prism/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,35 +33,11 @@ pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_l
}

/**
* Sets the -p command line option on the given options struct.
* Sets the command line option on the given options struct.
*/
PRISM_EXPORTED_FUNCTION void
pm_options_command_line_p_set(pm_options_t *options, bool command_line_p) {
options->command_line_p = command_line_p;
}

/**
* Sets the -n command line option on the given options struct.
*/
PRISM_EXPORTED_FUNCTION void
pm_options_command_line_n_set(pm_options_t *options, bool command_line_n) {
options->command_line_n = command_line_n;
}

/**
* Sets the -l command line option on the given options struct.
*/
PRISM_EXPORTED_FUNCTION void
pm_options_command_line_l_set(pm_options_t *options, bool command_line_l) {
options->command_line_l = command_line_l;
}

/**
* Sets the -a command line option on the given options struct.
*/
PRISM_EXPORTED_FUNCTION void
pm_options_command_line_a_set(pm_options_t *options, bool command_line_a) {
options->command_line_a = command_line_a;
pm_options_command_line_set(pm_options_t *options, uint8_t command_line) {
options->command_line = command_line;
}

/**
Expand Down Expand Up @@ -226,10 +202,7 @@ pm_options_read(pm_options_t *options, const char *data) {
}

options->frozen_string_literal = (*data++) ? true : false;
options->command_line_p = (*data++) ? true : false;
options->command_line_n = (*data++) ? true : false;
options->command_line_l = (*data++) ? true : false;
options->command_line_a = (*data++) ? true : false;
options->command_line = (uint8_t) *data++;
options->version = (pm_options_version_t) *data++;

uint32_t scopes_count = pm_options_read_u32(data);
Expand Down
78 changes: 41 additions & 37 deletions prism/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,49 @@ typedef struct {
*/
pm_options_version_t version;

/** 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;
} pm_options_t;

/** Whether or not the -p command line option has been set. */
bool command_line_p;
/**
* A bit representing whether or not the command line -a option was set. -a
* splits the input line $_ into $F.
*/
static const uint8_t PM_OPTIONS_COMMAND_LINE_A = 0x1;

/** Whether or not the -n command line option has been set. */
bool command_line_n;
/**
* A bit representing whether or not the command line -e option was set. -e
* allow the user to specify a script to be executed. This is necessary for
* prism to know because certain warnings are not generated when -e is used.
*/
static const uint8_t PM_OPTIONS_COMMAND_LINE_E = 0x2;

/** Whether or not the -l command line option has been set. */
bool command_line_l;
/**
* A bit representing whether or not the command line -l option was set. -l
* chomps the input line by default.
*/
static const uint8_t PM_OPTIONS_COMMAND_LINE_L = 0x4;

/** Whether or not the -a command line option has been set. */
bool command_line_a;
} pm_options_t;
/**
* A bit representing whether or not the command line -n option was set. -n
* wraps the script in a while gets loop.
*/
static const uint8_t PM_OPTIONS_COMMAND_LINE_N = 0x8;

/**
* A bit representing whether or not the command line -p option was set. -p
* prints the value of $_ at the end of each loop.
*/
static const uint8_t PM_OPTIONS_COMMAND_LINE_P = 0x10;

/**
* A bit representing whether or not the command line -x option was set. -x
* searches the input file for a shebang that matches the current Ruby engine.
*/
static const uint8_t PM_OPTIONS_COMMAND_LINE_X = 0x20;

/**
* Set the filepath option on the given options struct.
Expand Down Expand Up @@ -125,36 +153,12 @@ PRISM_EXPORTED_FUNCTION void pm_options_encoding_set(pm_options_t *options, cons
PRISM_EXPORTED_FUNCTION void pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_literal);

/**
* Sets the -p command line option on the given options struct.
*
* @param options The options struct to set the -p command line option on.
* @param command_line_p The -p command line option to set.
*/
PRISM_EXPORTED_FUNCTION void pm_options_command_line_p_set(pm_options_t *options, bool command_line_p);

/**
* Sets the -n command line option on the given options struct.
*
* @param options The options struct to set the -n command line option on.
* @param command_line_n The -n command line option to set.
*/
PRISM_EXPORTED_FUNCTION void pm_options_command_line_n_set(pm_options_t *options, bool command_line_n);

/**
* Sets the -l command line option on the given options struct.
*
* @param options The options struct to set the -l command line option on.
* @param command_line_l The -l command line option to set.
*/
PRISM_EXPORTED_FUNCTION void pm_options_command_line_l_set(pm_options_t *options, bool command_line_l);

/**
* Sets the -a command line option on the given options struct.
* Sets the command line option on the given options struct.
*
* @param options The options struct to set the -a command line option on.
* @param command_line_a The -a command line option to set.
* @param options The options struct to set the command line option on.
* @param command_line The command_line value to set.
*/
PRISM_EXPORTED_FUNCTION void pm_options_command_line_a_set(pm_options_t *options, bool command_line_a);
PRISM_EXPORTED_FUNCTION void pm_options_command_line_set(pm_options_t *options, uint8_t command_line);

/**
* Set the version option on the given options struct by parsing the given
Expand Down
27 changes: 3 additions & 24 deletions prism/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,9 @@ struct pm_parser {
/** The version of prism that we should use to parse. */
pm_options_version_t version;

/** The command line flags given from the options. */
uint8_t command_line;

/** Whether or not we're at the beginning of a command. */
bool command_start;

Expand Down Expand Up @@ -736,30 +739,6 @@ struct pm_parser {
* a true value.
*/
bool frozen_string_literal;

/**
* Whether or not -p was present on the command line that invoked the
* parser. -p prints the value of $_ at the end of each loop.
*/
bool command_line_p;

/**
* Whether or not -n was present on the command line that invoked the
* parser. -n wraps the script in a while gets loop.
*/
bool command_line_n;

/**
* Whether or not -l was present on the command line that invoked the
* parser. -l chomps the input line by default.
*/
bool command_line_l;

/**
* Whether or not -a was present on the command line that invoked the
* parser. -a splits the input line $_ into $F.
*/
bool command_line_a;
};

#endif