mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
[Universal parser] Decouple IMEMO from rb_ast_t
This patch removes the `VALUE flags` member from the `rb_ast_t` structure making `rb_ast_t` no longer an IMEMO object. ## Background We are trying to make the Ruby parser generated from parse.y a universal parser that can be used by other implementations such as mruby. To achieve this, it is necessary to exclude VALUE and IMEMO from parse.y, AST, and NODE. ## Summary (file by file) - `rubyparser.h` - Remove the `VALUE flags` member from `rb_ast_t` - `ruby_parser.c` and `internal/ruby_parser.h` - Use TypedData_Make_Struct VALUE which wraps `rb_ast_t` `in ast_alloc()` so that GC can manage it - You can retrieve `rb_ast_t` from the VALUE by `rb_ruby_ast_data_get()` - Change the return type of `rb_parser_compile_XXXX()` functions from `rb_ast_t *` to `VALUE` - rb_ruby_ast_new() which internally `calls ast_alloc()` is to create VALUE vast outside ruby_parser.c - `iseq.c` and `vm_core.h` - Amend the first parameter of `rb_iseq_new_XXXX()` functions from `rb_ast_body_t *` to `VALUE` - This keeps the VALUE of AST on the machine stack to prevent being removed by GC - `ast.c` - Almost all change is replacement `rb_ast_t *ast` with `VALUE vast` (sorry for the big diff) - Fix `node_memsize()` - Now it includes `rb_ast_local_table_link`, `tokens` and script_lines - `compile.c`, `load.c`, `node.c`, `parse.y`, `proc.c`, `ruby.c`, `template/prelude.c.tmpl`, `vm.c` and `vm_eval.c` - Follow-up due to the above changes - `imemo.{c|h}` - If an object with `imemo_ast` appears, considers it a bug Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
This commit is contained in:
parent
9b5bc8e6ea
commit
2244c58b00
18 changed files with 413 additions and 286 deletions
|
@ -293,9 +293,11 @@ arg_error(void)
|
|||
}
|
||||
|
||||
static rb_ast_t *
|
||||
ast_new(VALUE nb)
|
||||
ast_new(node_buffer_t *nb)
|
||||
{
|
||||
return IMEMO_NEW(rb_ast_t, imemo_ast, nb);
|
||||
rb_ast_t *ast = ruby_xcalloc(1, sizeof(rb_ast_t));
|
||||
ast->node_buffer = nb;
|
||||
return ast;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -742,69 +744,95 @@ parser_compile_generic(struct ruby_parser *parser, rb_parser_lex_gets_func *lex_
|
|||
return rb_parser_compile(parser->parser_params, lex_gets, fname, (rb_parser_input_data)input, start);
|
||||
}
|
||||
|
||||
rb_ast_t*
|
||||
static void
|
||||
ast_free(void *ptr)
|
||||
{
|
||||
rb_ast_t *ast = (rb_ast_t *)ptr;
|
||||
if (ast) {
|
||||
rb_ast_free(ast);
|
||||
}
|
||||
}
|
||||
|
||||
static const rb_data_type_t ast_data_type = {
|
||||
"AST",
|
||||
{
|
||||
NULL,
|
||||
ast_free,
|
||||
NULL, // No dsize() because this object does not appear in ObjectSpace.
|
||||
},
|
||||
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
||||
};
|
||||
|
||||
static VALUE
|
||||
ast_alloc(void)
|
||||
{
|
||||
rb_ast_t *ast;
|
||||
return TypedData_Make_Struct(0, rb_ast_t, &ast_data_type, ast);
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_parser_compile_file_path(VALUE vparser, VALUE fname, VALUE file, int start)
|
||||
{
|
||||
struct ruby_parser *parser;
|
||||
rb_ast_t *ast;
|
||||
VALUE vast = ast_alloc();
|
||||
|
||||
TypedData_Get_Struct(vparser, struct ruby_parser, &ruby_parser_data_type, parser);
|
||||
ast = parser_compile_file_path(parser, fname, file, start);
|
||||
DATA_PTR(vast) = parser_compile_file_path(parser, fname, file, start);
|
||||
RB_GC_GUARD(vparser);
|
||||
|
||||
return ast;
|
||||
return vast;
|
||||
}
|
||||
|
||||
rb_ast_t*
|
||||
VALUE
|
||||
rb_parser_compile_array(VALUE vparser, VALUE fname, VALUE array, int start)
|
||||
{
|
||||
struct ruby_parser *parser;
|
||||
rb_ast_t *ast;
|
||||
VALUE vast = ast_alloc();
|
||||
|
||||
TypedData_Get_Struct(vparser, struct ruby_parser, &ruby_parser_data_type, parser);
|
||||
ast = parser_compile_array(parser, fname, array, start);
|
||||
DATA_PTR(vast) = parser_compile_array(parser, fname, array, start);
|
||||
RB_GC_GUARD(vparser);
|
||||
|
||||
return ast;
|
||||
return vast;
|
||||
}
|
||||
|
||||
rb_ast_t*
|
||||
VALUE
|
||||
rb_parser_compile_generic(VALUE vparser, rb_parser_lex_gets_func *lex_gets, VALUE fname, VALUE input, int start)
|
||||
{
|
||||
struct ruby_parser *parser;
|
||||
rb_ast_t *ast;
|
||||
VALUE vast = ast_alloc();
|
||||
|
||||
TypedData_Get_Struct(vparser, struct ruby_parser, &ruby_parser_data_type, parser);
|
||||
ast = parser_compile_generic(parser, lex_gets, fname, input, start);
|
||||
DATA_PTR(vast) = parser_compile_generic(parser, lex_gets, fname, input, start);
|
||||
RB_GC_GUARD(vparser);
|
||||
|
||||
return ast;
|
||||
return vast;
|
||||
}
|
||||
|
||||
rb_ast_t*
|
||||
VALUE
|
||||
rb_parser_compile_string(VALUE vparser, const char *f, VALUE s, int line)
|
||||
{
|
||||
struct ruby_parser *parser;
|
||||
rb_ast_t *ast;
|
||||
VALUE vast = ast_alloc();
|
||||
|
||||
TypedData_Get_Struct(vparser, struct ruby_parser, &ruby_parser_data_type, parser);
|
||||
ast = parser_compile_string(parser, f, s, line);
|
||||
DATA_PTR(vast) = parser_compile_string(parser, f, s, line);
|
||||
RB_GC_GUARD(vparser);
|
||||
|
||||
return ast;
|
||||
return vast;
|
||||
}
|
||||
|
||||
rb_ast_t*
|
||||
VALUE
|
||||
rb_parser_compile_string_path(VALUE vparser, VALUE f, VALUE s, int line)
|
||||
{
|
||||
struct ruby_parser *parser;
|
||||
rb_ast_t *ast;
|
||||
VALUE vast = ast_alloc();
|
||||
|
||||
TypedData_Get_Struct(vparser, struct ruby_parser, &ruby_parser_data_type, parser);
|
||||
ast = parser_compile_string_path(parser, f, s, line);
|
||||
DATA_PTR(vast) = parser_compile_string_path(parser, f, s, line);
|
||||
RB_GC_GUARD(vparser);
|
||||
|
||||
return ast;
|
||||
return vast;
|
||||
}
|
||||
|
||||
VALUE
|
||||
|
@ -1086,3 +1114,26 @@ rb_parser_aset_script_lines_for(VALUE path, rb_parser_ary_t *lines)
|
|||
script_lines = rb_parser_build_script_lines_from(lines);
|
||||
rb_hash_aset(hash, path, script_lines);
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_ruby_ast_new(const NODE *const root, rb_parser_ary_t *script_lines)
|
||||
{
|
||||
VALUE vast = ast_alloc();
|
||||
rb_ast_t *ast = DATA_PTR(vast);
|
||||
ast->body = (rb_ast_body_t){
|
||||
.root = root,
|
||||
.frozen_string_literal = -1,
|
||||
.coverage_enabled = -1,
|
||||
.script_lines = script_lines
|
||||
};
|
||||
return vast;
|
||||
}
|
||||
|
||||
rb_ast_t *
|
||||
rb_ruby_ast_data_get(VALUE vast)
|
||||
{
|
||||
rb_ast_t *ast;
|
||||
if (NIL_P(vast)) return NULL;
|
||||
TypedData_Get_Struct(vast, rb_ast_t, &ast_data_type, ast);
|
||||
return ast;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue