summaryrefslogtreecommitdiff
path: root/ruby.c
diff options
context:
space:
mode:
authorHParker <[email protected]>2023-12-07 15:47:36 -0800
committerKevin Newton <[email protected]>2023-12-15 13:42:19 -0500
commit55326a915f25608be1d40ab32baa9fc57762615d (patch)
tree69dc288dcadf3e09206c287919be5c7d9711edc2 /ruby.c
parent655c02790ee5aca122d3593fadab5b41a42a1899 (diff)
Introduce --parser runtime flag
Introduce runtime flag for specifying the parser, ``` ruby --parser=prism ``` also update the description: ``` $ ruby --parser=prism --version ruby 3.3.0dev (2023-12-08T04:47:14Z add-parser-runtime.. 0616384c9f) +PRISM [x86_64-darwin23] ``` [Bug #20044]
Diffstat (limited to 'ruby.c')
-rw-r--r--ruby.c107
1 files changed, 71 insertions, 36 deletions
diff --git a/ruby.c b/ruby.c
index da3fbf2d44..19c70d36fd 100644
--- a/ruby.c
+++ b/ruby.c
@@ -56,7 +56,6 @@
#include "internal/thread.h"
#include "internal/ruby_parser.h"
#include "internal/variable.h"
-#include "prism_compile.h"
#include "ruby/encoding.h"
#include "ruby/thread.h"
#include "ruby/util.h"
@@ -362,6 +361,8 @@ usage(const char *name, int help, int highlight, int columns)
"enable or disable features. see below for available features"),
M("--external-encoding=encoding", ", --internal-encoding=encoding",
"specify the default external or internal character encoding"),
+ M("--parser={parse.y|prism}", ", --parser=prism",
+ "the parser used to parse Ruby code (experimental)"),
M("--backtrace-limit=num", "", "limit the maximum length of backtrace"),
M("--verbose", "", "turn on verbose mode and disable script from stdin"),
M("--version", "", "print the version number, then exit"),
@@ -1407,6 +1408,18 @@ proc_long_options(ruby_cmdline_options_t *opt, const char *s, long argc, char **
else if (is_option_with_arg("external-encoding", Qfalse, Qtrue)) {
set_external_encoding_once(opt, s, 0);
}
+ else if (is_option_with_arg("parser", Qfalse, Qtrue)) {
+ if (strcmp("prism", s) == 0) {
+ (*rb_ruby_prism_ptr()) = true;
+ rb_warn("The Prism compiler is currently experimental and compatibility with parse.y is not yet complete. Please report an issues you find on the prism issue tracker.");
+ }
+ else if (strcmp("parse.y", s) == 0) {
+ // default behavior
+ } else {
+ rb_raise(rb_eRuntimeError,
+ "unknown parser %s", s);
+ }
+ }
#if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING
else if (is_option_with_arg("source-encoding", Qfalse, Qtrue)) {
set_source_encoding_once(opt, s, 0);
@@ -2244,39 +2257,41 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
ruby_set_argv(argc, argv);
opt->sflag = process_sflag(opt->sflag);
- if (opt->e_script) {
- VALUE progname = rb_progname;
- rb_encoding *eenc;
- rb_parser_set_context(parser, 0, TRUE);
+ if (!(*rb_ruby_prism_ptr())) {
+ if (opt->e_script) {
+ VALUE progname = rb_progname;
+ rb_encoding *eenc;
+ rb_parser_set_context(parser, 0, TRUE);
- if (opt->src.enc.index >= 0) {
- eenc = rb_enc_from_index(opt->src.enc.index);
- }
- else {
- eenc = lenc;
+ if (opt->src.enc.index >= 0) {
+ eenc = rb_enc_from_index(opt->src.enc.index);
+ }
+ else {
+ eenc = lenc;
#if UTF8_PATH
- if (ienc) eenc = ienc;
+ if (ienc) eenc = ienc;
#endif
- }
+ }
#if UTF8_PATH
- if (eenc != uenc) {
- opt->e_script = str_conv_enc(opt->e_script, uenc, eenc);
- }
+ if (eenc != uenc) {
+ opt->e_script = str_conv_enc(opt->e_script, uenc, eenc);
+ }
#endif
- rb_enc_associate(opt->e_script, eenc);
- ruby_opt_init(opt);
- ruby_set_script_name(progname);
- rb_parser_set_options(parser, opt->do_print, opt->do_loop,
- opt->do_line, opt->do_split);
- ast = rb_parser_compile_string(parser, opt->script, opt->e_script, 1);
- }
- else {
- VALUE f;
- int xflag = opt->xflag;
- f = open_load_file(script_name, &xflag);
- opt->xflag = xflag != 0;
- rb_parser_set_context(parser, 0, f == rb_stdin);
- ast = load_file(parser, opt->script_name, f, 1, opt);
+ rb_enc_associate(opt->e_script, eenc);
+ ruby_opt_init(opt);
+ ruby_set_script_name(progname);
+ rb_parser_set_options(parser, opt->do_print, opt->do_loop,
+ opt->do_line, opt->do_split);
+ ast = rb_parser_compile_string(parser, opt->script, opt->e_script, 1);
+ }
+ else {
+ VALUE f;
+ int xflag = opt->xflag;
+ f = open_load_file(script_name, &xflag);
+ opt->xflag = xflag != 0;
+ rb_parser_set_context(parser, 0, f == rb_stdin);
+ ast = load_file(parser, opt->script_name, f, 1, opt);
+ }
}
ruby_set_script_name(opt->script_name);
if (dump & DUMP_BIT(yydebug)) {
@@ -2301,7 +2316,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
rb_enc_set_default_internal(Qnil);
rb_stdio_set_default_encoding();
- if (!ast->body.root) {
+ if (!(*rb_ruby_prism_ptr()) && !ast->body.root) {
rb_ast_dispose(ast);
return Qfalse;
}
@@ -2378,12 +2393,30 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
}
- rb_binding_t *toplevel_binding;
- GetBindingPtr(rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING")),
- toplevel_binding);
- const struct rb_block *base_block = toplevel_context(toplevel_binding);
- iseq = rb_iseq_new_main(&ast->body, opt->script_name, path, vm_block_iseq(base_block), !(dump & DUMP_BIT(insns_without_opt)));
- rb_ast_dispose(ast);
+ if ((*rb_ruby_prism_ptr())) {
+ pm_string_t input;
+ pm_options_t options = { 0 };
+
+ if (opt->e_script) {
+ pm_string_constant_init(&input, RSTRING_PTR(opt->e_script), RSTRING_LEN(opt->e_script));
+ pm_options_filepath_set(&options, "-e");
+ } else {
+ pm_string_mapped_init(&input, RSTRING_PTR(opt->script_name));
+ pm_options_filepath_set(&options, RSTRING_PTR(opt->script_name));
+ }
+
+ iseq = rb_iseq_new_main_prism(&input, &options, path);
+
+ pm_string_free(&input);
+ pm_options_free(&options);
+ } else {
+ rb_binding_t *toplevel_binding;
+ GetBindingPtr(rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING")),
+ toplevel_binding);
+ const struct rb_block *base_block = toplevel_context(toplevel_binding);
+ iseq = rb_iseq_new_main(&ast->body, opt->script_name, path, vm_block_iseq(base_block), !(dump & DUMP_BIT(insns_without_opt)));
+ rb_ast_dispose(ast);
+ }
}
if (dump & (DUMP_BIT(insns) | DUMP_BIT(insns_without_opt))) {
@@ -2940,6 +2973,8 @@ ruby_process_options(int argc, char **argv)
VALUE iseq;
const char *script_name = (argc > 0 && argv[0]) ? argv[0] : ruby_engine;
+ (*rb_ruby_prism_ptr()) = false;
+
if (!origarg.argv || origarg.argc <= 0) {
origarg.argc = argc;
origarg.argv = argv;