Before this commit, we were mixing a lot of concerns with the prism
compile between RubyVM::InstructionSequence and the general entry
points to the prism parser/compiler.

This commit makes all of the various prism-related APIs mirror
their corresponding APIs in the existing parser/compiler. This means
we now have the correct frame naming, and it's much easier to follow
where the logic actually flows. Furthermore this consolidates a lot
of the prism initialization, making it easier to see where we could
potentially be raising errors.
This commit is contained in:
Kevin Newton 2024-01-31 12:17:31 -05:00
Родитель 21031f0a84
Коммит 610636fd6b
8 изменённых файлов: 491 добавлений и 356 удалений

Просмотреть файл

@ -3273,6 +3273,7 @@ compile.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
compile.$(OBJEXT): $(top_srcdir)/internal/gc.h
compile.$(OBJEXT): $(top_srcdir)/internal/hash.h
compile.$(OBJEXT): $(top_srcdir)/internal/imemo.h
compile.$(OBJEXT): $(top_srcdir)/internal/io.h
compile.$(OBJEXT): $(top_srcdir)/internal/numeric.h
compile.$(OBJEXT): $(top_srcdir)/internal/object.h
compile.$(OBJEXT): $(top_srcdir)/internal/rational.h
@ -3484,6 +3485,7 @@ compile.$(OBJEXT): {$(VPATH)}internal/value_type.h
compile.$(OBJEXT): {$(VPATH)}internal/variable.h
compile.$(OBJEXT): {$(VPATH)}internal/warning_push.h
compile.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
compile.$(OBJEXT): {$(VPATH)}io.h
compile.$(OBJEXT): {$(VPATH)}iseq.h
compile.$(OBJEXT): {$(VPATH)}method.h
compile.$(OBJEXT): {$(VPATH)}missing.h

Просмотреть файл

@ -26,6 +26,7 @@
#include "internal/error.h"
#include "internal/gc.h"
#include "internal/hash.h"
#include "internal/io.h"
#include "internal/numeric.h"
#include "internal/object.h"
#include "internal/rational.h"
@ -980,20 +981,6 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node)
return iseq_setup(iseq, ret);
}
static VALUE rb_translate_prism(pm_parser_t *parser, rb_iseq_t *iseq, pm_scope_node_t *scope_node, LINK_ANCHOR *const ret);
VALUE
rb_iseq_compile_prism_node(rb_iseq_t * iseq, pm_scope_node_t *scope_node, pm_parser_t *parser)
{
DECL_ANCHOR(ret);
INIT_ANCHOR(ret);
CHECK(rb_translate_prism(parser, iseq, scope_node, ret));
CHECK(iseq_setup_insn(iseq, ret));
return iseq_setup(iseq, ret);
}
static int
rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
{

336
iseq.c
Просмотреть файл

@ -875,6 +875,18 @@ rb_iseq_new_top(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath
ISEQ_TYPE_TOP, &COMPILE_OPTION_DEFAULT);
}
/**
* The main entry-point into the prism compiler when a file is required.
*/
rb_iseq_t *
pm_iseq_new_top(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent)
{
// iseq_new_setup_coverage(path, ast, 0);
return pm_iseq_new_with_opt(node, name, path, realpath, 0, parent, 0,
ISEQ_TYPE_TOP, &COMPILE_OPTION_DEFAULT);
}
rb_iseq_t *
rb_iseq_new_main(const rb_ast_body_t *ast, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt)
{
@ -885,6 +897,20 @@ rb_iseq_new_main(const rb_ast_body_t *ast, VALUE path, VALUE realpath, const rb_
parent, 0, ISEQ_TYPE_MAIN, opt ? &COMPILE_OPTION_DEFAULT : &COMPILE_OPTION_FALSE);
}
/**
* The main entry-point into the prism compiler when a file is executed as the
* main file in the program.
*/
rb_iseq_t *
pm_iseq_new_main(pm_scope_node_t *node, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt)
{
// iseq_new_setup_coverage(path, ast, 0);
return pm_iseq_new_with_opt(node, rb_fstring_lit("<main>"),
path, realpath, 0,
parent, 0, ISEQ_TYPE_MAIN, opt ? &COMPILE_OPTION_DEFAULT : &COMPILE_OPTION_FALSE);
}
rb_iseq_t *
rb_iseq_new_eval(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_iseq_t *parent, int isolated_depth)
{
@ -947,41 +973,39 @@ rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE rea
return iseq_translate(iseq);
}
VALUE rb_iseq_compile_prism_node(rb_iseq_t * iseq, pm_scope_node_t *scope_node, pm_parser_t *parser);
/**
* Initialize an rb_code_location_t with a prism location.
* This is a step in the prism compiler that is called once all of the various
* options have been established. It is called from one of the pm_iseq_new_*
* functions or from the RubyVM::InstructionSequence APIs. It is responsible for
* allocating the instruction sequence, calling into the compiler, and returning
* the built instruction sequence.
*
* Importantly, this is also the function where the compiler is re-entered to
* compile child instruction sequences. A child instruction sequence is always
* compiled using a scope node, which is why we cast it explicitly to that here
* in the parameters (as opposed to accepting a generic pm_node_t *).
*/
static void
pm_code_location(rb_code_location_t *code_location, const pm_newline_list_t *newline_list, const pm_location_t *location)
{
pm_line_column_t start = pm_newline_list_line_column(newline_list, location->start);
pm_line_column_t end = pm_newline_list_line_column(newline_list, location->end);
*code_location = (rb_code_location_t) {
.beg_pos = { .lineno = (int) start.line, .column = (int) start.column },
.end_pos = { .lineno = (int) end.line, .column = (int) end.column }
};
}
rb_iseq_t *
pm_iseq_new_with_opt(pm_scope_node_t *scope_node, pm_parser_t *parser, VALUE name, VALUE path, VALUE realpath,
pm_iseq_new_with_opt(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath,
int first_lineno, const rb_iseq_t *parent, int isolated_depth,
enum rb_iseq_type type, const rb_compile_option_t *option)
{
rb_iseq_t *iseq = iseq_alloc();
VALUE script_lines = Qnil;
if (!option) option = &COMPILE_OPTION_DEFAULT;
rb_code_location_t code_location;
pm_code_location(&code_location, &parser->newline_list, &scope_node->base.location);
pm_location_t *location = &node->base.location;
pm_line_column_t start = pm_newline_list_line_column(&node->parser->newline_list, location->start);
pm_line_column_t end = pm_newline_list_line_column(&node->parser->newline_list, location->end);
// TODO: node_id
int node_id = -1;
prepare_iseq_build(iseq, name, path, realpath, first_lineno, &code_location, node_id,
parent, isolated_depth, type, script_lines, option);
rb_code_location_t code_location = (rb_code_location_t) {
.beg_pos = { .lineno = (int) start.line, .column = (int) start.column },
.end_pos = { .lineno = (int) end.line, .column = (int) end.column }
};
rb_iseq_compile_prism_node(iseq, scope_node, parser);
prepare_iseq_build(iseq, name, path, realpath, first_lineno, &code_location, -1,
parent, isolated_depth, type, Qnil, option);
pm_iseq_compile_node(iseq, node);
finish_iseq_build(iseq);
return iseq_translate(iseq);
@ -1186,6 +1210,44 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, V
return iseq;
}
static rb_iseq_t *
pm_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, VALUE opt)
{
rb_iseq_t *iseq = NULL;
rb_compile_option_t option;
int ln;
VALUE name = rb_fstring_lit("<compiled>");
/* safe results first */
make_compile_option(&option, opt);
ln = NUM2INT(line);
StringValueCStr(file);
pm_parse_result_t result = { 0 };
VALUE error;
if (RB_TYPE_P(src, T_FILE)) {
VALUE filepath = rb_io_path(src);
error = pm_parse_file(&result, filepath);
RB_GC_GUARD(filepath);
}
else {
src = StringValue(src);
error = pm_parse_string(&result, src, file);
}
if (error == Qnil) {
iseq = pm_iseq_new_with_opt(&result.node, name, file, realpath, ln, NULL, 0, ISEQ_TYPE_TOP, &option);
pm_parse_result_free(&result);
}
else {
pm_parse_result_free(&result);
rb_exc_raise(error);
}
return iseq;
}
VALUE
rb_iseq_path(const rb_iseq_t *iseq)
{
@ -1398,53 +1460,42 @@ iseqw_s_compile(int argc, VALUE *argv, VALUE self)
return iseqw_new(rb_iseq_compile_with_option(src, file, path, line, opt));
}
static void
iseqw_s_compile_prism_compile(pm_parser_t *parser, VALUE optimize, rb_iseq_t *iseq, VALUE file, VALUE path, int first_lineno)
{
pm_node_t *node = pm_parse(parser);
if (parser->error_list.size > 0) {
pm_buffer_t buffer = { 0 };
pm_parser_errors_format(parser, &buffer, rb_stderr_tty_p());
pm_buffer_prepend_string(&buffer, "syntax errors found\n", 20);
VALUE error = rb_exc_new(rb_eSyntaxError, pm_buffer_value(&buffer), pm_buffer_length(&buffer));
pm_buffer_free(&buffer);
pm_node_destroy(parser, node);
// TODO: We need to set the backtrace based on the ISEQ.
// VALUE path = pathobj_path(ISEQ_BODY(iseq)->location.pathobj);
// rb_funcallv(error, rb_intern("set_backtrace"), 1, &path);
rb_exc_raise(error);
} else {
rb_code_location_t code_location;
pm_code_location(&code_location, &parser->newline_list, &node->location);
rb_compile_option_t option;
make_compile_option(&option, optimize);
prepare_iseq_build(iseq, rb_fstring_lit("<compiled>"), file, path, first_lineno, &code_location, -1, NULL, 0, ISEQ_TYPE_TOP, Qnil, &option);
pm_scope_node_t scope_node;
pm_scope_node_init(node, &scope_node, NULL, parser);
ID *constants = calloc(parser->constant_pool.size, sizeof(ID));
rb_encoding *encoding = rb_enc_find(parser->encoding->name);
for (uint32_t index = 0; index < parser->constant_pool.size; index++) {
pm_constant_t *constant = &parser->constant_pool.constants[index];
constants[index] = rb_intern3((const char *) constant->start, constant->length, encoding);
}
scope_node.constants = constants;
rb_iseq_compile_prism_node(iseq, &scope_node, parser);
finish_iseq_build(iseq);
pm_scope_node_destroy(&scope_node);
pm_node_destroy(parser, node);
free(constants);
}
}
/*
* call-seq:
* InstructionSequence.compile_prism(source[, file[, path[, line[, options]]]]) -> iseq
*
* Takes +source+, which can be a string of Ruby code, or an open +File+ object.
* that contains Ruby source code. It parses and compiles using prism.
*
* Optionally takes +file+, +path+, and +line+ which describe the file path,
* real path and first line number of the ruby code in +source+ which are
* metadata attached to the returned +iseq+.
*
* +file+ is used for `__FILE__` and exception backtrace. +path+ is used for
* +require_relative+ base. It is recommended these should be the same full
* path.
*
* +options+, which can be +true+, +false+ or a +Hash+, is used to
* modify the default behavior of the Ruby iseq compiler.
*
* For details regarding valid compile options see ::compile_option=.
*
* RubyVM::InstructionSequence.compile("a = 1 + 2")
* #=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
*
* path = "test.rb"
* RubyVM::InstructionSequence.compile(File.read(path), path, File.expand_path(path))
* #=> <RubyVM::InstructionSequence:<compiled>@test.rb:1>
*
* file = File.open("test.rb")
* RubyVM::InstructionSequence.compile(file)
* #=> <RubyVM::InstructionSequence:<compiled>@<compiled>:1>
*
* path = File.expand_path("test.rb")
* RubyVM::InstructionSequence.compile(File.read(path), path, path)
* #=> <RubyVM::InstructionSequence:<compiled>@/absolute/path/to/test.rb:1>
*
*/
static VALUE
iseqw_s_compile_prism(int argc, VALUE *argv, VALUE self)
{
@ -1467,87 +1518,7 @@ iseqw_s_compile_prism(int argc, VALUE *argv, VALUE self)
Check_Type(path, T_STRING);
Check_Type(file, T_STRING);
pm_options_t options = { 0 };
pm_options_filepath_set(&options, RSTRING_PTR(file));
int start_line = NUM2INT(line);
pm_options_line_set(&options, start_line);
pm_parser_t parser;
VALUE file_path = Qnil;
pm_string_t input;
if (RB_TYPE_P(src, T_FILE)) {
file_path = rb_io_path(src); /* rb_io_t->pathv gets frozen anyways */
pm_string_mapped_init(&input, RSTRING_PTR(file_path));
}
else {
Check_Type(src, T_STRING);
input.source = (const uint8_t *)RSTRING_PTR(src);
input.length = RSTRING_LEN(src);
input.type = PM_STRING_SHARED;
}
pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), &options);
rb_iseq_t *iseq = iseq_alloc();
iseqw_s_compile_prism_compile(&parser, opt, iseq, file, path, start_line);
RB_GC_GUARD(file_path);
pm_parser_free(&parser);
pm_options_free(&options);
pm_string_free(&input);
return iseqw_new(iseq);
}
static VALUE
iseqw_s_compile_file_prism(int argc, VALUE *argv, VALUE self)
{
VALUE file = Qnil, opt = Qnil;
int i;
i = rb_scan_args(argc, argv, "1*:", &file, NULL, &opt);
if (i > 1+NIL_P(opt)) rb_error_arity(argc, 1, 5);
switch (i) {
case 2: opt = argv[--i];
}
FilePathValue(file);
file = rb_fstring(file); /* rb_io_t->pathv gets frozen anyways */
pm_string_t input;
pm_string_mapped_init(&input, RSTRING_PTR(file));
pm_options_t options = { 0 };
pm_options_filepath_set(&options, RSTRING_PTR(file));
pm_parser_t parser;
pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), &options);
rb_iseq_t *iseq = iseq_alloc();
iseqw_s_compile_prism_compile(&parser, opt, iseq, file, rb_realpath_internal(Qnil, file, 1), 1);
pm_parser_free(&parser);
pm_string_free(&input);
pm_options_free(&options);
return iseqw_new(iseq);
}
rb_iseq_t *
rb_iseq_new_main_prism(pm_string_t *input, pm_options_t *options, VALUE script_name, VALUE path, VALUE optimize)
{
pm_parser_t parser;
pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options);
if (NIL_P(path)) path = rb_fstring_lit("<compiled>");
int start_line = 0;
pm_options_line_set(options, start_line);
rb_iseq_t *iseq = iseq_alloc();
iseqw_s_compile_prism_compile(&parser, optimize, iseq, script_name, path, start_line);
pm_parser_free(&parser);
return iseq;
return iseqw_new(pm_iseq_compile_with_option(src, file, path, line, opt));
}
/*
@ -1616,6 +1587,67 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self)
return ret;
}
/*
* call-seq:
* InstructionSequence.compile_file_prism(file[, options]) -> iseq
*
* Takes +file+, a String with the location of a Ruby source file, reads,
* parses and compiles the file, and returns +iseq+, the compiled
* InstructionSequence with source location metadata set. It parses and
* compiles using prism.
*
* Optionally takes +options+, which can be +true+, +false+ or a +Hash+, to
* modify the default behavior of the Ruby iseq compiler.
*
* For details regarding valid compile options see ::compile_option=.
*
* # /tmp/hello.rb
* puts "Hello, world!"
*
* # elsewhere
* RubyVM::InstructionSequence.compile_file_prism("/tmp/hello.rb")
* #=> <RubyVM::InstructionSequence:<main>@/tmp/hello.rb>
*/
static VALUE
iseqw_s_compile_file_prism(int argc, VALUE *argv, VALUE self)
{
VALUE file, opt = Qnil, ret;
rb_compile_option_t option;
int i;
i = rb_scan_args(argc, argv, "1*:", &file, NULL, &opt);
if (i > 1+NIL_P(opt)) rb_error_arity(argc, 1, 2);
switch (i) {
case 2: opt = argv[--i];
}
FilePathValue(file);
file = rb_fstring(file); /* rb_io_t->pathv gets frozen anyways */
rb_execution_context_t *ec = GET_EC();
VALUE v = rb_vm_push_frame_fname(ec, file);
pm_parse_result_t result = { 0 };
VALUE error = pm_parse_file(&result, file);
if (error == Qnil) {
make_compile_option(&option, opt);
ret = iseqw_new(pm_iseq_new_with_opt(&result.node, rb_fstring_lit("<main>"),
file,
rb_realpath_internal(Qnil, file, 1),
1, NULL, 0, ISEQ_TYPE_TOP, &option));
pm_parse_result_free(&result);
rb_vm_pop_frame(ec);
RB_GC_GUARD(v);
return ret;
} else {
pm_parse_result_free(&result);
rb_vm_pop_frame(ec);
RB_GC_GUARD(v);
rb_exc_raise(error);
}
}
/*
* call-seq:
* InstructionSequence.compile_option = options

1
iseq.h
Просмотреть файл

@ -172,7 +172,6 @@ void rb_iseq_init_trace(rb_iseq_t *iseq);
int rb_iseq_add_local_tracepoint_recursively(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line, bool target_bmethod);
int rb_iseq_remove_local_tracepoint_recursively(const rb_iseq_t *iseq, VALUE tpval);
const rb_iseq_t *rb_iseq_load_iseq(VALUE fname);
rb_iseq_t * rb_iseq_new_main_prism(pm_string_t *input, pm_options_t *options, VALUE script_name, VALUE path, VALUE optimize);
#if VM_INSN_INFO_TABLE_IMPL == 2
unsigned int *rb_iseq_insns_info_decode_positions(const struct rb_iseq_constant_body *body);

40
load.c
Просмотреть файл

@ -737,38 +737,40 @@ load_iseq_eval(rb_execution_context_t *ec, VALUE fname)
const rb_iseq_t *iseq = rb_iseq_load_iseq(fname);
if (!iseq) {
rb_execution_context_t *ec = GET_EC();
VALUE v = rb_vm_push_frame_fname(ec, fname);
rb_thread_t *th = rb_ec_thread_ptr(ec);
VALUE realpath_map = get_loaded_features_realpath_map(th->vm);
if (*rb_ruby_prism_ptr()) {
pm_string_t input;
pm_options_t options = { 0 };
pm_parse_result_t result = { 0 };
VALUE error = pm_parse_file(&result, fname);
pm_string_mapped_init(&input, RSTRING_PTR(fname));
pm_options_filepath_set(&options, RSTRING_PTR(fname));
pm_parser_t parser;
pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), &options);
iseq = rb_iseq_new_main_prism(&input, &options, fname, fname, Qnil);
pm_string_free(&input);
pm_options_free(&options);
if (error == Qnil) {
iseq = pm_iseq_new_top(&result.node, rb_fstring_lit("<top (required)>"), fname, realpath_internal_cached(realpath_map, fname), NULL);
pm_parse_result_free(&result);
}
else {
rb_vm_pop_frame(ec);
RB_GC_GUARD(v);
pm_parse_result_free(&result);
rb_exc_raise(error);
}
}
else {
rb_execution_context_t *ec = GET_EC();
VALUE v = rb_vm_push_frame_fname(ec, fname);
rb_ast_t *ast;
VALUE parser = rb_parser_new();
rb_parser_set_context(parser, NULL, FALSE);
ast = (rb_ast_t *)rb_parser_load_file(parser, fname);
rb_thread_t *th = rb_ec_thread_ptr(ec);
VALUE realpath_map = get_loaded_features_realpath_map(th->vm);
iseq = rb_iseq_new_top(&ast->body, rb_fstring_lit("<top (required)>"),
fname, realpath_internal_cached(realpath_map, fname), NULL);
rb_ast_dispose(ast);
rb_vm_pop_frame(ec);
RB_GC_GUARD(v);
}
rb_vm_pop_frame(ec);
RB_GC_GUARD(v);
}
rb_exec_event_hook_script_compiled(ec, iseq, Qnil);
rb_iseq_eval(iseq);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -35,3 +35,23 @@ typedef struct pm_scope_node {
void pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_t *previous, pm_parser_t *parser);
void pm_scope_node_destroy(pm_scope_node_t *scope_node);
bool *rb_ruby_prism_ptr(void);
typedef struct {
pm_parser_t parser;
pm_options_t options;
pm_string_t input;
pm_scope_node_t node;
bool parsed;
} pm_parse_result_t;
VALUE pm_parse_file(pm_parse_result_t *result, VALUE filepath);
VALUE pm_parse_string(pm_parse_result_t *result, VALUE source, VALUE filepath);
void pm_parse_result_free(pm_parse_result_t *result);
rb_iseq_t *pm_iseq_new(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, enum rb_iseq_type);
rb_iseq_t *pm_iseq_new_top(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent);
rb_iseq_t *pm_iseq_new_main(pm_scope_node_t *node, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt);
rb_iseq_t *pm_iseq_new_eval(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_iseq_t *parent, int isolated_depth);
rb_iseq_t *pm_iseq_new_with_opt(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_iseq_t *parent, int isolated_depth, enum rb_iseq_type, const rb_compile_option_t*);
VALUE pm_iseq_compile_node(rb_iseq_t *iseq, pm_scope_node_t *node);

35
ruby.c
Просмотреть файл

@ -2404,10 +2404,13 @@ 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);
if ((*rb_ruby_prism_ptr())) {
pm_string_t input;
pm_options_t options = { 0 };
pm_parse_result_t result = { 0 };
VALUE error;
if (strcmp(opt->script, "-") == 0) {
int xflag = opt->xflag;
@ -2415,30 +2418,26 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
opt->xflag = xflag != 0;
rb_warn("Prism support for streaming code from stdin is not currently supported");
pm_string_constant_init(&input, RSTRING_PTR(rb_source), RSTRING_LEN(rb_source));
pm_options_filepath_set(&options, RSTRING_PTR(opt->script_name));
error = pm_parse_string(&result, rb_source, opt->script_name);
}
else 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");
error = pm_parse_string(&result, opt->e_script, rb_str_new2("-e"));
}
else {
pm_string_mapped_init(&input, RSTRING_PTR(opt->script_name));
pm_options_filepath_set(&options, RSTRING_PTR(opt->script_name));
error = pm_parse_file(&result, opt->script_name);
}
VALUE optimize = dump & DUMP_BIT(insns_without_opt) ? Qfalse : Qnil;
iseq = rb_iseq_new_main_prism(&input, &options, opt->script_name, path, optimize);
ruby_opt_init(opt);
pm_string_free(&input);
pm_options_free(&options);
if (error == Qnil) {
ruby_opt_init(opt);
iseq = pm_iseq_new_main(&result.node, opt->script_name, path, vm_block_iseq(base_block), !(dump & DUMP_BIT(insns_without_opt)));
pm_parse_result_free(&result);
}
else {
pm_parse_result_free(&result);
rb_exc_raise(error);
}
}
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);
}