diff options
-rw-r--r-- | ast.c | 294 | ||||
-rw-r--r-- | compile.c | 18 | ||||
-rw-r--r-- | imemo.c | 7 | ||||
-rw-r--r-- | internal/imemo.h | 2 | ||||
-rw-r--r-- | internal/ruby_parser.h | 15 | ||||
-rw-r--r-- | iseq.c | 76 | ||||
-rw-r--r-- | load.c | 6 | ||||
-rw-r--r-- | mini_builtin.c | 10 | ||||
-rw-r--r-- | node.c | 67 | ||||
-rw-r--r-- | parse.y | 1 | ||||
-rw-r--r-- | proc.c | 2 | ||||
-rw-r--r-- | ruby.c | 38 | ||||
-rw-r--r-- | ruby_parser.c | 95 | ||||
-rw-r--r-- | rubyparser.h | 6 | ||||
-rw-r--r-- | template/prelude.c.tmpl | 30 | ||||
-rw-r--r-- | vm.c | 14 | ||||
-rw-r--r-- | vm_core.h | 10 | ||||
-rw-r--r-- | vm_eval.c | 8 |
18 files changed, 413 insertions, 286 deletions
@@ -16,7 +16,7 @@ static VALUE rb_mAST; static VALUE rb_cNode; struct ASTNodeData { - rb_ast_t *ast; + VALUE vast; const NODE *node; }; @@ -24,14 +24,16 @@ static void node_gc_mark(void *ptr) { struct ASTNodeData *data = (struct ASTNodeData *)ptr; - rb_gc_mark((VALUE)data->ast); + rb_gc_mark(data->vast); } static size_t node_memsize(const void *ptr) { struct ASTNodeData *data = (struct ASTNodeData *)ptr; - return rb_ast_memsize(data->ast); + rb_ast_t *ast = rb_ruby_ast_data_get(data->vast); + + return sizeof(struct ASTNodeData) + rb_ast_memsize(ast); } static const rb_data_type_t rb_node_type = { @@ -44,22 +46,22 @@ static const rb_data_type_t rb_node_type = { static VALUE rb_ast_node_alloc(VALUE klass); static void -setup_node(VALUE obj, rb_ast_t *ast, const NODE *node) +setup_node(VALUE obj, VALUE vast, const NODE *node) { struct ASTNodeData *data; TypedData_Get_Struct(obj, struct ASTNodeData, &rb_node_type, data); - data->ast = ast; + data->vast = vast; data->node = node; } static VALUE -ast_new_internal(rb_ast_t *ast, const NODE *node) +ast_new_internal(VALUE vast, const NODE *node) { VALUE obj; obj = rb_ast_node_alloc(rb_cNode); - setup_node(obj, ast, node); + setup_node(obj, vast, node); return obj; } @@ -74,14 +76,16 @@ ast_parse_new(void) } static VALUE -ast_parse_done(rb_ast_t *ast) +ast_parse_done(VALUE vast) { + rb_ast_t *ast = rb_ruby_ast_data_get(vast); + if (!ast->body.root) { rb_ast_dispose(ast); rb_exc_raise(GET_EC()->errinfo); } - return ast_new_internal(ast, (NODE *)ast->body.root); + return ast_new_internal(vast, (NODE *)ast->body.root); } static VALUE @@ -93,15 +97,15 @@ ast_s_parse(rb_execution_context_t *ec, VALUE module, VALUE str, VALUE keep_scri static VALUE rb_ast_parse_str(VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens) { - rb_ast_t *ast = 0; + VALUE vast; StringValue(str); VALUE vparser = ast_parse_new(); if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser); if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser); if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser); - ast = rb_parser_compile_string_path(vparser, Qnil, str, 1); - return ast_parse_done(ast); + vast = rb_parser_compile_string_path(vparser, Qnil, str, 1); + return ast_parse_done(vast); } static VALUE @@ -114,7 +118,7 @@ static VALUE rb_ast_parse_file(VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens) { VALUE f; - rb_ast_t *ast = 0; + VALUE vast = Qnil; rb_encoding *enc = rb_utf8_encoding(); f = rb_file_open_str(path, "r"); @@ -123,26 +127,26 @@ rb_ast_parse_file(VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VAL if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser); if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser); if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser); - ast = rb_parser_compile_file_path(vparser, Qnil, f, 1); + vast = rb_parser_compile_file_path(vparser, Qnil, f, 1); rb_io_close(f); - return ast_parse_done(ast); + return ast_parse_done(vast); } static VALUE rb_ast_parse_array(VALUE array, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens) { - rb_ast_t *ast = 0; + VALUE vast = Qnil; array = rb_check_array_type(array); VALUE vparser = ast_parse_new(); if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser); if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser); if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser); - ast = rb_parser_compile_array(vparser, Qnil, array, 1); - return ast_parse_done(ast); + vast = rb_parser_compile_array(vparser, Qnil, array, 1); + return ast_parse_done(vast); } -static VALUE node_children(rb_ast_t*, const NODE*); +static VALUE node_children(VALUE, const NODE*); static VALUE node_find(VALUE self, const int node_id) @@ -154,7 +158,7 @@ node_find(VALUE self, const int node_id) if (nd_node_id(data->node) == node_id) return self; - ary = node_children(data->ast, data->node); + ary = node_children(data->vast, data->node); for (i = 0; i < RARRAY_LEN(ary); i++) { VALUE child = RARRAY_AREF(ary, i); @@ -277,10 +281,10 @@ ast_node_node_id(rb_execution_context_t *ec, VALUE self) return INT2FIX(nd_node_id(data->node)); } -#define NEW_CHILD(ast, node) node ? ast_new_internal(ast, node) : Qnil +#define NEW_CHILD(vast, node) (node ? ast_new_internal(vast, node) : Qnil) static VALUE -rb_ary_new_from_node_args(rb_ast_t *ast, long n, ...) +rb_ary_new_from_node_args(VALUE vast, long n, ...) { va_list ar; VALUE ary; @@ -292,39 +296,39 @@ rb_ary_new_from_node_args(rb_ast_t *ast, long n, ...) for (i=0; i<n; i++) { NODE *node; node = va_arg(ar, NODE *); - rb_ary_push(ary, NEW_CHILD(ast, node)); + rb_ary_push(ary, NEW_CHILD(vast, node)); } va_end(ar); return ary; } static VALUE -dump_block(rb_ast_t *ast, const struct RNode_BLOCK *node) +dump_block(VALUE vast, const struct RNode_BLOCK *node) { VALUE ary = rb_ary_new(); do { - rb_ary_push(ary, NEW_CHILD(ast, node->nd_head)); + rb_ary_push(ary, NEW_CHILD(vast, node->nd_head)); } while (node->nd_next && nd_type_p(node->nd_next, NODE_BLOCK) && (node = RNODE_BLOCK(node->nd_next), 1)); if (node->nd_next) { - rb_ary_push(ary, NEW_CHILD(ast, node->nd_next)); + rb_ary_push(ary, NEW_CHILD(vast, node->nd_next)); } return ary; } static VALUE -dump_array(rb_ast_t *ast, const struct RNode_LIST *node) +dump_array(VALUE vast, const struct RNode_LIST *node) { VALUE ary = rb_ary_new(); - rb_ary_push(ary, NEW_CHILD(ast, node->nd_head)); + rb_ary_push(ary, NEW_CHILD(vast, node->nd_head)); while (node->nd_next && nd_type_p(node->nd_next, NODE_LIST)) { node = RNODE_LIST(node->nd_next); - rb_ary_push(ary, NEW_CHILD(ast, node->nd_head)); + rb_ary_push(ary, NEW_CHILD(vast, node->nd_head)); } - rb_ary_push(ary, NEW_CHILD(ast, node->nd_next)); + rb_ary_push(ary, NEW_CHILD(vast, node->nd_next)); return ary; } @@ -346,155 +350,155 @@ no_name_rest(void) } static VALUE -rest_arg(rb_ast_t *ast, const NODE *rest_arg) +rest_arg(VALUE vast, const NODE *rest_arg) { - return NODE_NAMED_REST_P(rest_arg) ? NEW_CHILD(ast, rest_arg) : no_name_rest(); + return NODE_NAMED_REST_P(rest_arg) ? NEW_CHILD(vast, rest_arg) : no_name_rest(); } static VALUE -node_children(rb_ast_t *ast, const NODE *node) +node_children(VALUE vast, const NODE *node) { char name[sizeof("$") + DECIMAL_SIZE_OF(long)]; enum node_type type = nd_type(node); switch (type) { case NODE_BLOCK: - return dump_block(ast, RNODE_BLOCK(node)); + return dump_block(vast, RNODE_BLOCK(node)); case NODE_IF: - return rb_ary_new_from_node_args(ast, 3, RNODE_IF(node)->nd_cond, RNODE_IF(node)->nd_body, RNODE_IF(node)->nd_else); + return rb_ary_new_from_node_args(vast, 3, RNODE_IF(node)->nd_cond, RNODE_IF(node)->nd_body, RNODE_IF(node)->nd_else); case NODE_UNLESS: - return rb_ary_new_from_node_args(ast, 3, RNODE_UNLESS(node)->nd_cond, RNODE_UNLESS(node)->nd_body, RNODE_UNLESS(node)->nd_else); + return rb_ary_new_from_node_args(vast, 3, RNODE_UNLESS(node)->nd_cond, RNODE_UNLESS(node)->nd_body, RNODE_UNLESS(node)->nd_else); case NODE_CASE: - return rb_ary_new_from_node_args(ast, 2, RNODE_CASE(node)->nd_head, RNODE_CASE(node)->nd_body); + return rb_ary_new_from_node_args(vast, 2, RNODE_CASE(node)->nd_head, RNODE_CASE(node)->nd_body); case NODE_CASE2: - return rb_ary_new_from_node_args(ast, 2, RNODE_CASE2(node)->nd_head, RNODE_CASE2(node)->nd_body); + return rb_ary_new_from_node_args(vast, 2, RNODE_CASE2(node)->nd_head, RNODE_CASE2(node)->nd_body); case NODE_CASE3: - return rb_ary_new_from_node_args(ast, 2, RNODE_CASE3(node)->nd_head, RNODE_CASE3(node)->nd_body); + return rb_ary_new_from_node_args(vast, 2, RNODE_CASE3(node)->nd_head, RNODE_CASE3(node)->nd_body); case NODE_WHEN: - return rb_ary_new_from_node_args(ast, 3, RNODE_WHEN(node)->nd_head, RNODE_WHEN(node)->nd_body, RNODE_WHEN(node)->nd_next); + return rb_ary_new_from_node_args(vast, 3, RNODE_WHEN(node)->nd_head, RNODE_WHEN(node)->nd_body, RNODE_WHEN(node)->nd_next); case NODE_IN: - return rb_ary_new_from_node_args(ast, 3, RNODE_IN(node)->nd_head, RNODE_IN(node)->nd_body, RNODE_IN(node)->nd_next); + return rb_ary_new_from_node_args(vast, 3, RNODE_IN(node)->nd_head, RNODE_IN(node)->nd_body, RNODE_IN(node)->nd_next); case NODE_WHILE: case NODE_UNTIL: - return rb_ary_push(rb_ary_new_from_node_args(ast, 2, RNODE_WHILE(node)->nd_cond, RNODE_WHILE(node)->nd_body), + return rb_ary_push(rb_ary_new_from_node_args(vast, 2, RNODE_WHILE(node)->nd_cond, RNODE_WHILE(node)->nd_body), RBOOL(RNODE_WHILE(node)->nd_state)); case NODE_ITER: case NODE_FOR: - return rb_ary_new_from_node_args(ast, 2, RNODE_ITER(node)->nd_iter, RNODE_ITER(node)->nd_body); + return rb_ary_new_from_node_args(vast, 2, RNODE_ITER(node)->nd_iter, RNODE_ITER(node)->nd_body); case NODE_FOR_MASGN: - return rb_ary_new_from_node_args(ast, 1, RNODE_FOR_MASGN(node)->nd_var); + return rb_ary_new_from_node_args(vast, 1, RNODE_FOR_MASGN(node)->nd_var); case NODE_BREAK: - return rb_ary_new_from_node_args(ast, 1, RNODE_BREAK(node)->nd_stts); + return rb_ary_new_from_node_args(vast, 1, RNODE_BREAK(node)->nd_stts); case NODE_NEXT: - return rb_ary_new_from_node_args(ast, 1, RNODE_NEXT(node)->nd_stts); + return rb_ary_new_from_node_args(vast, 1, RNODE_NEXT(node)->nd_stts); case NODE_RETURN: - return rb_ary_new_from_node_args(ast, 1, RNODE_RETURN(node)->nd_stts); + return rb_ary_new_from_node_args(vast, 1, RNODE_RETURN(node)->nd_stts); case NODE_REDO: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(vast, 0); case NODE_RETRY: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(vast, 0); case NODE_BEGIN: - return rb_ary_new_from_node_args(ast, 1, RNODE_BEGIN(node)->nd_body); + return rb_ary_new_from_node_args(vast, 1, RNODE_BEGIN(node)->nd_body); case NODE_RESCUE: - return rb_ary_new_from_node_args(ast, 3, RNODE_RESCUE(node)->nd_head, RNODE_RESCUE(node)->nd_resq, RNODE_RESCUE(node)->nd_else); + return rb_ary_new_from_node_args(vast, 3, RNODE_RESCUE(node)->nd_head, RNODE_RESCUE(node)->nd_resq, RNODE_RESCUE(node)->nd_else); case NODE_RESBODY: - return rb_ary_new_from_node_args(ast, 3, RNODE_RESBODY(node)->nd_args, RNODE_RESBODY(node)->nd_body, RNODE_RESBODY(node)->nd_next); + return rb_ary_new_from_node_args(vast, 3, RNODE_RESBODY(node)->nd_args, RNODE_RESBODY(node)->nd_body, RNODE_RESBODY(node)->nd_next); case NODE_ENSURE: - return rb_ary_new_from_node_args(ast, 2, RNODE_ENSURE(node)->nd_head, RNODE_ENSURE(node)->nd_ensr); + return rb_ary_new_from_node_args(vast, 2, RNODE_ENSURE(node)->nd_head, RNODE_ENSURE(node)->nd_ensr); case NODE_AND: case NODE_OR: { VALUE ary = rb_ary_new(); while (1) { - rb_ary_push(ary, NEW_CHILD(ast, RNODE_AND(node)->nd_1st)); + rb_ary_push(ary, NEW_CHILD(vast, RNODE_AND(node)->nd_1st)); if (!RNODE_AND(node)->nd_2nd || !nd_type_p(RNODE_AND(node)->nd_2nd, type)) break; node = RNODE_AND(node)->nd_2nd; } - rb_ary_push(ary, NEW_CHILD(ast, RNODE_AND(node)->nd_2nd)); + rb_ary_push(ary, NEW_CHILD(vast, RNODE_AND(node)->nd_2nd)); return ary; } case NODE_MASGN: if (NODE_NAMED_REST_P(RNODE_MASGN(node)->nd_args)) { - return rb_ary_new_from_node_args(ast, 3, RNODE_MASGN(node)->nd_value, RNODE_MASGN(node)->nd_head, RNODE_MASGN(node)->nd_args); + return rb_ary_new_from_node_args(vast, 3, RNODE_MASGN(node)->nd_value, RNODE_MASGN(node)->nd_head, RNODE_MASGN(node)->nd_args); } else { - return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_MASGN(node)->nd_value), - NEW_CHILD(ast, RNODE_MASGN(node)->nd_head), + return rb_ary_new_from_args(3, NEW_CHILD(vast, RNODE_MASGN(node)->nd_value), + NEW_CHILD(vast, RNODE_MASGN(node)->nd_head), no_name_rest()); } case NODE_LASGN: if (NODE_REQUIRED_KEYWORD_P(RNODE_LASGN(node)->nd_value)) { return rb_ary_new_from_args(2, var_name(RNODE_LASGN(node)->nd_vid), ID2SYM(rb_intern("NODE_SPECIAL_REQUIRED_KEYWORD"))); } - return rb_ary_new_from_args(2, var_name(RNODE_LASGN(node)->nd_vid), NEW_CHILD(ast, RNODE_LASGN(node)->nd_value)); + return rb_ary_new_from_args(2, var_name(RNODE_LASGN(node)->nd_vid), NEW_CHILD(vast, RNODE_LASGN(node)->nd_value)); case NODE_DASGN: if (NODE_REQUIRED_KEYWORD_P(RNODE_DASGN(node)->nd_value)) { return rb_ary_new_from_args(2, var_name(RNODE_DASGN(node)->nd_vid), ID2SYM(rb_intern("NODE_SPECIAL_REQUIRED_KEYWORD"))); } - return rb_ary_new_from_args(2, var_name(RNODE_DASGN(node)->nd_vid), NEW_CHILD(ast, RNODE_DASGN(node)->nd_value)); + return rb_ary_new_from_args(2, var_name(RNODE_DASGN(node)->nd_vid), NEW_CHILD(vast, RNODE_DASGN(node)->nd_value)); case NODE_IASGN: - return rb_ary_new_from_args(2, var_name(RNODE_IASGN(node)->nd_vid), NEW_CHILD(ast, RNODE_IASGN(node)->nd_value)); + return rb_ary_new_from_args(2, var_name(RNODE_IASGN(node)->nd_vid), NEW_CHILD(vast, RNODE_IASGN(node)->nd_value)); case NODE_CVASGN: - return rb_ary_new_from_args(2, var_name(RNODE_CVASGN(node)->nd_vid), NEW_CHILD(ast, RNODE_CVASGN(node)->nd_value)); + return rb_ary_new_from_args(2, var_name(RNODE_CVASGN(node)->nd_vid), NEW_CHILD(vast, RNODE_CVASGN(node)->nd_value)); case NODE_GASGN: - return rb_ary_new_from_args(2, var_name(RNODE_GASGN(node)->nd_vid), NEW_CHILD(ast, RNODE_GASGN(node)->nd_value)); + return rb_ary_new_from_args(2, var_name(RNODE_GASGN(node)->nd_vid), NEW_CHILD(vast, RNODE_GASGN(node)->nd_value)); case NODE_CDECL: if (RNODE_CDECL(node)->nd_vid) { - return rb_ary_new_from_args(2, ID2SYM(RNODE_CDECL(node)->nd_vid), NEW_CHILD(ast, RNODE_CDECL(node)->nd_value)); + return rb_ary_new_from_args(2, ID2SYM(RNODE_CDECL(node)->nd_vid), NEW_CHILD(vast, RNODE_CDECL(node)->nd_value)); } - return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_CDECL(node)->nd_else), ID2SYM(RNODE_COLON2(RNODE_CDECL(node)->nd_else)->nd_mid), NEW_CHILD(ast, RNODE_CDECL(node)->nd_value)); + return rb_ary_new_from_args(3, NEW_CHILD(vast, RNODE_CDECL(node)->nd_else), ID2SYM(RNODE_COLON2(RNODE_CDECL(node)->nd_else)->nd_mid), NEW_CHILD(vast, RNODE_CDECL(node)->nd_value)); case NODE_OP_ASGN1: - return rb_ary_new_from_args(4, NEW_CHILD(ast, RNODE_OP_ASGN1(node)->nd_recv), + return rb_ary_new_from_args(4, NEW_CHILD(vast, RNODE_OP_ASGN1(node)->nd_recv), ID2SYM(RNODE_OP_ASGN1(node)->nd_mid), - NEW_CHILD(ast, RNODE_OP_ASGN1(node)->nd_index), - NEW_CHILD(ast, RNODE_OP_ASGN1(node)->nd_rvalue)); + NEW_CHILD(vast, RNODE_OP_ASGN1(node)->nd_index), + NEW_CHILD(vast, RNODE_OP_ASGN1(node)->nd_rvalue)); case NODE_OP_ASGN2: - return rb_ary_new_from_args(5, NEW_CHILD(ast, RNODE_OP_ASGN2(node)->nd_recv), + return rb_ary_new_from_args(5, NEW_CHILD(vast, RNODE_OP_ASGN2(node)->nd_recv), RBOOL(RNODE_OP_ASGN2(node)->nd_aid), ID2SYM(RNODE_OP_ASGN2(node)->nd_vid), ID2SYM(RNODE_OP_ASGN2(node)->nd_mid), - NEW_CHILD(ast, RNODE_OP_ASGN2(node)->nd_value)); + NEW_CHILD(vast, RNODE_OP_ASGN2(node)->nd_value)); case NODE_OP_ASGN_AND: - return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_OP_ASGN_AND(node)->nd_head), ID2SYM(idANDOP), - NEW_CHILD(ast, RNODE_OP_ASGN_AND(node)->nd_value)); + return rb_ary_new_from_args(3, NEW_CHILD(vast, RNODE_OP_ASGN_AND(node)->nd_head), ID2SYM(idANDOP), + NEW_CHILD(vast, RNODE_OP_ASGN_AND(node)->nd_value)); case NODE_OP_ASGN_OR: - return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_OP_ASGN_OR(node)->nd_head), ID2SYM(idOROP), - NEW_CHILD(ast, RNODE_OP_ASGN_OR(node)->nd_value)); + return rb_ary_new_from_args(3, NEW_CHILD(vast, RNODE_OP_ASGN_OR(node)->nd_head), ID2SYM(idOROP), + NEW_CHILD(vast, RNODE_OP_ASGN_OR(node)->nd_value)); case NODE_OP_CDECL: - return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_OP_CDECL(node)->nd_head), + return rb_ary_new_from_args(3, NEW_CHILD(vast, RNODE_OP_CDECL(node)->nd_head), ID2SYM(RNODE_OP_CDECL(node)->nd_aid), - NEW_CHILD(ast, RNODE_OP_CDECL(node)->nd_value)); + NEW_CHILD(vast, RNODE_OP_CDECL(node)->nd_value)); case NODE_CALL: - return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_CALL(node)->nd_recv), + return rb_ary_new_from_args(3, NEW_CHILD(vast, RNODE_CALL(node)->nd_recv), ID2SYM(RNODE_CALL(node)->nd_mid), - NEW_CHILD(ast, RNODE_CALL(node)->nd_args)); + NEW_CHILD(vast, RNODE_CALL(node)->nd_args)); case NODE_OPCALL: - return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_OPCALL(node)->nd_recv), + return rb_ary_new_from_args(3, NEW_CHILD(vast, RNODE_OPCALL(node)->nd_recv), ID2SYM(RNODE_OPCALL(node)->nd_mid), - NEW_CHILD(ast, RNODE_OPCALL(node)->nd_args)); + NEW_CHILD(vast, RNODE_OPCALL(node)->nd_args)); case NODE_QCALL: - return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_QCALL(node)->nd_recv), + return rb_ary_new_from_args(3, NEW_CHILD(vast, RNODE_QCALL(node)->nd_recv), ID2SYM(RNODE_QCALL(node)->nd_mid), - NEW_CHILD(ast, RNODE_QCALL(node)->nd_args)); + NEW_CHILD(vast, RNODE_QCALL(node)->nd_args)); case NODE_FCALL: return rb_ary_new_from_args(2, ID2SYM(RNODE_FCALL(node)->nd_mid), - NEW_CHILD(ast, RNODE_FCALL(node)->nd_args)); + NEW_CHILD(vast, RNODE_FCALL(node)->nd_args)); case NODE_VCALL: return rb_ary_new_from_args(1, ID2SYM(RNODE_VCALL(node)->nd_mid)); case NODE_SUPER: - return rb_ary_new_from_node_args(ast, 1, RNODE_SUPER(node)->nd_args); + return rb_ary_new_from_node_args(vast, 1, RNODE_SUPER(node)->nd_args); case NODE_ZSUPER: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(vast, 0); case NODE_LIST: - return dump_array(ast, RNODE_LIST(node)); + return dump_array(vast, RNODE_LIST(node)); case NODE_ZLIST: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(vast, 0); case NODE_HASH: - return rb_ary_new_from_node_args(ast, 1, RNODE_HASH(node)->nd_head); + return rb_ary_new_from_node_args(vast, 1, RNODE_HASH(node)->nd_head); case NODE_YIELD: - return rb_ary_new_from_node_args(ast, 1, RNODE_YIELD(node)->nd_head); + return rb_ary_new_from_node_args(vast, 1, RNODE_YIELD(node)->nd_head); case NODE_LVAR: return rb_ary_new_from_args(1, var_name(RNODE_LVAR(node)->nd_vid)); case NODE_DVAR: @@ -519,11 +523,11 @@ node_children(rb_ast_t *ast, const NODE *node) return rb_ary_new_from_args(1, rb_node_regx_string_val(node)); case NODE_MATCH2: if (RNODE_MATCH2(node)->nd_args) { - return rb_ary_new_from_node_args(ast, 3, RNODE_MATCH2(node)->nd_recv, RNODE_MATCH2(node)->nd_value, RNODE_MATCH2(node)->nd_args); + return rb_ary_new_from_node_args(vast, 3, RNODE_MATCH2(node)->nd_recv, RNODE_MATCH2(node)->nd_value, RNODE_MATCH2(node)->nd_args); } - return rb_ary_new_from_node_args(ast, 2, RNODE_MATCH2(node)->nd_recv, RNODE_MATCH2(node)->nd_value); + return rb_ary_new_from_node_args(vast, 2, RNODE_MATCH2(node)->nd_recv, RNODE_MATCH2(node)->nd_value); case NODE_MATCH3: - return rb_ary_new_from_node_args(ast, 2, RNODE_MATCH3(node)->nd_recv, RNODE_MATCH3(node)->nd_value); + return rb_ary_new_from_node_args(vast, 2, RNODE_MATCH3(node)->nd_recv, RNODE_MATCH3(node)->nd_value); case NODE_STR: case NODE_XSTR: return rb_ary_new_from_args(1, rb_node_str_string_val(node)); @@ -538,7 +542,7 @@ node_children(rb_ast_t *ast, const NODE *node) case NODE_REGX: return rb_ary_new_from_args(1, rb_node_regx_string_val(node)); case NODE_ONCE: - return rb_ary_new_from_node_args(ast, 1, RNODE_ONCE(node)->nd_body); + return rb_ary_new_from_node_args(vast, 1, RNODE_ONCE(node)->nd_body); case NODE_DSTR: case NODE_DXSTR: case NODE_DREGX: @@ -547,91 +551,91 @@ node_children(rb_ast_t *ast, const NODE *node) struct RNode_LIST *n = RNODE_DSTR(node)->nd_next; VALUE head = Qnil, next = Qnil; if (n) { - head = NEW_CHILD(ast, n->nd_head); - next = NEW_CHILD(ast, n->nd_next); + head = NEW_CHILD(vast, n->nd_head); + next = NEW_CHILD(vast, n->nd_next); } return rb_ary_new_from_args(3, rb_node_dstr_string_val(node), head, next); } case NODE_SYM: return rb_ary_new_from_args(1, rb_node_sym_string_val(node)); case NODE_EVSTR: - return rb_ary_new_from_node_args(ast, 1, RNODE_EVSTR(node)->nd_body); + return rb_ary_new_from_node_args(vast, 1, RNODE_EVSTR(node)->nd_body); case NODE_ARGSCAT: - return rb_ary_new_from_node_args(ast, 2, RNODE_ARGSCAT(node)->nd_head, RNODE_ARGSCAT(node)->nd_body); + return rb_ary_new_from_node_args(vast, 2, RNODE_ARGSCAT(node)->nd_head, RNODE_ARGSCAT(node)->nd_body); case NODE_ARGSPUSH: - return rb_ary_new_from_node_args(ast, 2, RNODE_ARGSPUSH(node)->nd_head, RNODE_ARGSPUSH(node)->nd_body); + return rb_ary_new_from_node_args(vast, 2, RNODE_ARGSPUSH(node)->nd_head, RNODE_ARGSPUSH(node)->nd_body); case NODE_SPLAT: - return rb_ary_new_from_node_args(ast, 1, RNODE_SPLAT(node)->nd_head); + return rb_ary_new_from_node_args(vast, 1, RNODE_SPLAT(node)->nd_head); case NODE_BLOCK_PASS: - return rb_ary_new_from_node_args(ast, 2, RNODE_BLOCK_PASS(node)->nd_head, RNODE_BLOCK_PASS(node)->nd_body); + return rb_ary_new_from_node_args(vast, 2, RNODE_BLOCK_PASS(node)->nd_head, RNODE_BLOCK_PASS(node)->nd_body); case NODE_DEFN: - return rb_ary_new_from_args(2, ID2SYM(RNODE_DEFN(node)->nd_mid), NEW_CHILD(ast, RNODE_DEFN(node)->nd_defn)); + return rb_ary_new_from_args(2, ID2SYM(RNODE_DEFN(node)->nd_mid), NEW_CHILD(vast, RNODE_DEFN(node)->nd_defn)); case NODE_DEFS: - return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_DEFS(node)->nd_recv), ID2SYM(RNODE_DEFS(node)->nd_mid), NEW_CHILD(ast, RNODE_DEFS(node)->nd_defn)); + return rb_ary_new_from_args(3, NEW_CHILD(vast, RNODE_DEFS(node)->nd_recv), ID2SYM(RNODE_DEFS(node)->nd_mid), NEW_CHILD(vast, RNODE_DEFS(node)->nd_defn)); case NODE_ALIAS: - return rb_ary_new_from_node_args(ast, 2, RNODE_ALIAS(node)->nd_1st, RNODE_ALIAS(node)->nd_2nd); + return rb_ary_new_from_node_args(vast, 2, RNODE_ALIAS(node)->nd_1st, RNODE_ALIAS(node)->nd_2nd); case NODE_VALIAS: return rb_ary_new_from_args(2, ID2SYM(RNODE_VALIAS(node)->nd_alias), ID2SYM(RNODE_VALIAS(node)->nd_orig)); case NODE_UNDEF: - return rb_ary_new_from_node_args(ast, 1, RNODE_UNDEF(node)->nd_undef); + return rb_ary_new_from_node_args(vast, 1, RNODE_UNDEF(node)->nd_undef); case NODE_CLASS: - return rb_ary_new_from_node_args(ast, 3, RNODE_CLASS(node)->nd_cpath, RNODE_CLASS(node)->nd_super, RNODE_CLASS(node)->nd_body); + return rb_ary_new_from_node_args(vast, 3, RNODE_CLASS(node)->nd_cpath, RNODE_CLASS(node)->nd_super, RNODE_CLASS(node)->nd_body); case NODE_MODULE: - return rb_ary_new_from_node_args(ast, 2, RNODE_MODULE(node)->nd_cpath, RNODE_MODULE(node)->nd_body); + return rb_ary_new_from_node_args(vast, 2, RNODE_MODULE(node)->nd_cpath, RNODE_MODULE(node)->nd_body); case NODE_SCLASS: - return rb_ary_new_from_node_args(ast, 2, RNODE_SCLASS(node)->nd_recv, RNODE_SCLASS(node)->nd_body); + return rb_ary_new_from_node_args(vast, 2, RNODE_SCLASS(node)->nd_recv, RNODE_SCLASS(node)->nd_body); case NODE_COLON2: - return rb_ary_new_from_args(2, NEW_CHILD(ast, RNODE_COLON2(node)->nd_head), ID2SYM(RNODE_COLON2(node)->nd_mid)); + return rb_ary_new_from_args(2, NEW_CHILD(vast, RNODE_COLON2(node)->nd_head), ID2SYM(RNODE_COLON2(node)->nd_mid)); case NODE_COLON3: return rb_ary_new_from_args(1, ID2SYM(RNODE_COLON3(node)->nd_mid)); case NODE_DOT2: case NODE_DOT3: case NODE_FLIP2: case NODE_FLIP3: - return rb_ary_new_from_node_args(ast, 2, RNODE_DOT2(node)->nd_beg, RNODE_DOT2(node)->nd_end); + return rb_ary_new_from_node_args(vast, 2, RNODE_DOT2(node)->nd_beg, RNODE_DOT2(node)->nd_end); case NODE_SELF: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(vast, 0); case NODE_NIL: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(vast, 0); case NODE_TRUE: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(vast, 0); case NODE_FALSE: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(vast, 0); case NODE_ERRINFO: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(vast, 0); case NODE_DEFINED: - return rb_ary_new_from_node_args(ast, 1, RNODE_DEFINED(node)->nd_head); + return rb_ary_new_from_node_args(vast, 1, RNODE_DEFINED(node)->nd_head); case NODE_POSTEXE: - return rb_ary_new_from_node_args(ast, 1, RNODE_POSTEXE(node)->nd_body); + return rb_ary_new_from_node_args(vast, 1, RNODE_POSTEXE(node)->nd_body); case NODE_ATTRASGN: - return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_ATTRASGN(node)->nd_recv), ID2SYM(RNODE_ATTRASGN(node)->nd_mid), NEW_CHILD(ast, RNODE_ATTRASGN(node)->nd_args)); + return rb_ary_new_from_args(3, NEW_CHILD(vast, RNODE_ATTRASGN(node)->nd_recv), ID2SYM(RNODE_ATTRASGN(node)->nd_mid), NEW_CHILD(vast, RNODE_ATTRASGN(node)->nd_args)); case NODE_LAMBDA: - return rb_ary_new_from_node_args(ast, 1, RNODE_LAMBDA(node)->nd_body); + return rb_ary_new_from_node_args(vast, 1, RNODE_LAMBDA(node)->nd_body); case NODE_OPT_ARG: - return rb_ary_new_from_node_args(ast, 2, RNODE_OPT_ARG(node)->nd_body, RNODE_OPT_ARG(node)->nd_next); + return rb_ary_new_from_node_args(vast, 2, RNODE_OPT_ARG(node)->nd_body, RNODE_OPT_ARG(node)->nd_next); case NODE_KW_ARG: - return rb_ary_new_from_node_args(ast, 2, RNODE_KW_ARG(node)->nd_body, RNODE_KW_ARG(node)->nd_next); + return rb_ary_new_from_node_args(vast, 2, RNODE_KW_ARG(node)->nd_body, RNODE_KW_ARG(node)->nd_next); case NODE_POSTARG: if (NODE_NAMED_REST_P(RNODE_POSTARG(node)->nd_1st)) { - return rb_ary_new_from_node_args(ast, 2, RNODE_POSTARG(node)->nd_1st, RNODE_POSTARG(node)->nd_2nd); + return rb_ary_new_from_node_args(vast, 2, RNODE_POSTARG(node)->nd_1st, RNODE_POSTARG(node)->nd_2nd); } return rb_ary_new_from_args(2, no_name_rest(), - NEW_CHILD(ast, RNODE_POSTARG(node)->nd_2nd)); + NEW_CHILD(vast, RNODE_POSTARG(node)->nd_2nd)); case NODE_ARGS: { struct rb_args_info *ainfo = &RNODE_ARGS(node)->nd_ainfo; return rb_ary_new_from_args(10, INT2NUM(ainfo->pre_args_num), - NEW_CHILD(ast, ainfo->pre_init), - NEW_CHILD(ast, (NODE *)ainfo->opt_args), + NEW_CHILD(vast, ainfo->pre_init), + NEW_CHILD(vast, (NODE *)ainfo->opt_args), var_name(ainfo->first_post_arg), INT2NUM(ainfo->post_args_num), - NEW_CHILD(ast, ainfo->post_init), + NEW_CHILD(vast, ainfo->post_init), (ainfo->rest_arg == NODE_SPECIAL_EXCESSIVE_COMMA ? ID2SYM(rb_intern("NODE_SPECIAL_EXCESSIVE_COMMA")) : var_name(ainfo->rest_arg)), - (ainfo->no_kwarg ? Qfalse : NEW_CHILD(ast, (NODE *)ainfo->kw_args)), - (ainfo->no_kwarg ? Qfalse : NEW_CHILD(ast, ainfo->kw_rest_arg)), + (ainfo->no_kwarg ? Qfalse : NEW_CHILD(vast, (NODE *)ainfo->kw_args)), + (ainfo->no_kwarg ? Qfalse : NEW_CHILD(vast, ainfo->kw_rest_arg)), var_name(ainfo->block_arg)); } case NODE_SCOPE: @@ -642,35 +646,35 @@ node_children(rb_ast_t *ast, const NODE *node) for (i = 0; i < size; i++) { rb_ary_push(locals, var_name(tbl->ids[i])); } - return rb_ary_new_from_args(3, locals, NEW_CHILD(ast, (NODE *)RNODE_SCOPE(node)->nd_args), NEW_CHILD(ast, RNODE_SCOPE(node)->nd_body)); + return rb_ary_new_from_args(3, locals, NEW_CHILD(vast, (NODE *)RNODE_SCOPE(node)->nd_args), NEW_CHILD(vast, RNODE_SCOPE(node)->nd_body)); } case NODE_ARYPTN: { - VALUE rest = rest_arg(ast, RNODE_ARYPTN(node)->rest_arg); + VALUE rest = rest_arg(vast, RNODE_ARYPTN(node)->rest_arg); return rb_ary_new_from_args(4, - NEW_CHILD(ast, RNODE_ARYPTN(node)->nd_pconst), - NEW_CHILD(ast, RNODE_ARYPTN(node)->pre_args), + NEW_CHILD(vast, RNODE_ARYPTN(node)->nd_pconst), + NEW_CHILD(vast, RNODE_ARYPTN(node)->pre_args), rest, - NEW_CHILD(ast, RNODE_ARYPTN(node)->post_args)); + NEW_CHILD(vast, RNODE_ARYPTN(node)->post_args)); } case NODE_FNDPTN: { - VALUE pre_rest = rest_arg(ast, RNODE_FNDPTN(node)->pre_rest_arg); - VALUE post_rest = rest_arg(ast, RNODE_FNDPTN(node)->post_rest_arg); + VALUE pre_rest = rest_arg(vast, RNODE_FNDPTN(node)->pre_rest_arg); + VALUE post_rest = rest_arg(vast, RNODE_FNDPTN(node)->post_rest_arg); return rb_ary_new_from_args(4, - NEW_CHILD(ast, RNODE_FNDPTN(node)->nd_pconst), + NEW_CHILD(vast, RNODE_FNDPTN(node)->nd_pconst), pre_rest, - NEW_CHILD(ast, RNODE_FNDPTN(node)->args), + NEW_CHILD(vast, RNODE_FNDPTN(node)->args), post_rest); } case NODE_HSHPTN: { VALUE kwrest = RNODE_HSHPTN(node)->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD ? ID2SYM(rb_intern("NODE_SPECIAL_NO_REST_KEYWORD")) : - NEW_CHILD(ast, RNODE_HSHPTN(node)->nd_pkwrestarg); + NEW_CHILD(vast, RNODE_HSHPTN(node)->nd_pkwrestarg); return rb_ary_new_from_args(3, - NEW_CHILD(ast, RNODE_HSHPTN(node)->nd_pconst), - NEW_CHILD(ast, RNODE_HSHPTN(node)->nd_pkwargs), + NEW_CHILD(vast, RNODE_HSHPTN(node)->nd_pconst), + NEW_CHILD(vast, RNODE_HSHPTN(node)->nd_pkwargs), kwrest); } case NODE_LINE: @@ -680,7 +684,7 @@ node_children(rb_ast_t *ast, const NODE *node) case NODE_ENCODING: return rb_ary_new_from_args(1, rb_node_encoding_val(node)); case NODE_ERROR: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(vast, 0); case NODE_ARGS_AUX: case NODE_LAST: break; @@ -695,7 +699,7 @@ ast_node_children(rb_execution_context_t *ec, VALUE self) struct ASTNodeData *data; TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data); - return node_children(data->ast, data->node); + return node_children(data->vast, data->node); } static VALUE @@ -739,13 +743,15 @@ ast_node_all_tokens(rb_execution_context_t *ec, VALUE self) { long i; struct ASTNodeData *data; + rb_ast_t *ast; rb_parser_ary_t *parser_tokens; rb_parser_ast_token_t *parser_token; VALUE str, loc, token, all_tokens; TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data); + ast = rb_ruby_ast_data_get(data->vast); - parser_tokens = data->ast->node_buffer->tokens; + parser_tokens = ast->node_buffer->tokens; if (parser_tokens == NULL) { return Qnil; } @@ -792,8 +798,10 @@ static VALUE ast_node_script_lines(rb_execution_context_t *ec, VALUE self) { struct ASTNodeData *data; + rb_ast_t *ast; TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data); - rb_parser_ary_t *ret = data->ast->body.script_lines; + ast = rb_ruby_ast_data_get(data->vast); + rb_parser_ary_t *ret = ast->body.script_lines; if (!ret || FIXNUM_P((VALUE)ret)) return Qnil; return rb_parser_build_script_lines_from(ret); } @@ -1478,16 +1478,11 @@ new_child_iseq(rb_iseq_t *iseq, const NODE *const node, VALUE name, const rb_iseq_t *parent, enum rb_iseq_type type, int line_no) { rb_iseq_t *ret_iseq; - rb_ast_body_t ast; - - ast.root = node; - ast.frozen_string_literal = -1; - ast.coverage_enabled = -1; - ast.script_lines = NULL; + VALUE vast = rb_ruby_ast_new(node, NULL); debugs("[new_child_iseq]> ---------------------------------------\n"); int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth; - ret_iseq = rb_iseq_new_with_opt(&ast, name, + ret_iseq = rb_iseq_new_with_opt(vast, name, rb_iseq_path(iseq), rb_iseq_realpath(iseq), line_no, parent, isolated_depth ? isolated_depth + 1 : 0, @@ -8753,15 +8748,10 @@ compile_builtin_mandatory_only_method(rb_iseq_t *iseq, const NODE *node, const N scope_node.nd_body = mandatory_node(iseq, node); scope_node.nd_args = &args_node; - rb_ast_body_t ast = { - .root = RNODE(&scope_node), - .frozen_string_literal = -1, - .coverage_enabled = -1, - .script_lines = NULL - }; + VALUE vast = rb_ruby_ast_new(RNODE(&scope_node), NULL); ISEQ_BODY(iseq)->mandatory_only_iseq = - rb_iseq_new_with_opt(&ast, rb_iseq_base_label(iseq), + rb_iseq_new_with_opt(vast, rb_iseq_base_label(iseq), rb_iseq_path(iseq), rb_iseq_realpath(iseq), nd_line(line_node), NULL, 0, ISEQ_TYPE_METHOD, ISEQ_COMPILE_DATA(iseq)->option, @@ -130,7 +130,7 @@ rb_imemo_memsize(VALUE obj) size_t size = 0; switch (imemo_type(obj)) { case imemo_ast: - size += rb_ast_memsize((rb_ast_t *)obj); + rb_bug("imemo_ast is obsolete"); break; case imemo_callcache: @@ -273,7 +273,7 @@ rb_imemo_mark_and_move(VALUE obj, bool reference_updating) { switch (imemo_type(obj)) { case imemo_ast: - // TODO: Make AST decoupled from IMEMO + rb_bug("imemo_ast is obsolete"); break; case imemo_callcache: { @@ -513,8 +513,7 @@ rb_imemo_free(VALUE obj) { switch (imemo_type(obj)) { case imemo_ast: - rb_ast_free((rb_ast_t *)obj); - RB_DEBUG_COUNTER_INC(obj_imemo_ast); + rb_bug("imemo_ast is obsolete"); break; case imemo_callcache: diff --git a/internal/imemo.h b/internal/imemo.h index 673e7e668a..36c0776987 100644 --- a/internal/imemo.h +++ b/internal/imemo.h @@ -39,7 +39,7 @@ enum imemo_type { imemo_ment = 6, imemo_iseq = 7, imemo_tmpbuf = 8, - imemo_ast = 9, + imemo_ast = 9, // Obsolete due to the universal parser imemo_parser_strterm = 10, imemo_callinfo = 11, imemo_callcache = 12, diff --git a/internal/ruby_parser.h b/internal/ruby_parser.h index afb8909429..76200ae4e4 100644 --- a/internal/ruby_parser.h +++ b/internal/ruby_parser.h @@ -22,7 +22,7 @@ rb_parser_t *rb_parser_params_new(void); #endif VALUE rb_parser_set_context(VALUE, const struct rb_iseq_struct *, int); VALUE rb_parser_new(void); -rb_ast_t *rb_parser_compile_string_path(VALUE vparser, VALUE fname, VALUE src, int line); +VALUE rb_parser_compile_string_path(VALUE vparser, VALUE fname, VALUE src, int line); VALUE rb_str_new_parser_string(rb_parser_string_t *str); VALUE rb_str_new_mutable_parser_string(rb_parser_string_t *str); VALUE rb_parser_lex_get_str(struct lex_pointer_string *ptr_str); @@ -48,15 +48,15 @@ VALUE rb_parser_set_yydebug(VALUE, VALUE); VALUE rb_parser_build_script_lines_from(rb_parser_ary_t *script_lines); void rb_parser_aset_script_lines_for(VALUE path, rb_parser_ary_t *script_lines); void rb_parser_set_options(VALUE, int, int, int, int); -void *rb_parser_load_file(VALUE parser, VALUE name); +VALUE rb_parser_load_file(VALUE parser, VALUE name); void rb_parser_set_script_lines(VALUE vparser); void rb_parser_error_tolerant(VALUE vparser); void rb_parser_keep_tokens(VALUE vparser); -rb_ast_t *rb_parser_compile_string(VALUE, const char*, VALUE, int); -rb_ast_t *rb_parser_compile_file_path(VALUE vparser, VALUE fname, VALUE input, int line); -rb_ast_t *rb_parser_compile_generic(VALUE vparser, rb_parser_lex_gets_func *lex_gets, VALUE fname, VALUE input, int line); -rb_ast_t *rb_parser_compile_array(VALUE vparser, VALUE fname, VALUE array, int start); +VALUE rb_parser_compile_string(VALUE, const char*, VALUE, int); +VALUE rb_parser_compile_file_path(VALUE vparser, VALUE fname, VALUE input, int line); +VALUE rb_parser_compile_generic(VALUE vparser, rb_parser_lex_gets_func *lex_gets, VALUE fname, VALUE input, int line); +VALUE rb_parser_compile_array(VALUE vparser, VALUE fname, VALUE array, int start); enum lex_state_bits { EXPR_BEG_bit, /* ignore newline, +/- is a sign. */ @@ -97,4 +97,7 @@ enum lex_state_e { EXPR_NONE = 0 }; +VALUE rb_ruby_ast_new(const NODE *const root, rb_parser_ary_t *script_lines); +rb_ast_t *rb_ruby_ast_data_get(VALUE vast); + #endif /* INTERNAL_RUBY_PARSE_H */ @@ -839,31 +839,32 @@ make_compile_option_value(rb_compile_option_t *option) } rb_iseq_t * -rb_iseq_new(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, +rb_iseq_new(const VALUE vast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, enum rb_iseq_type type) { - return rb_iseq_new_with_opt(ast, name, path, realpath, 0, parent, + return rb_iseq_new_with_opt(vast, name, path, realpath, 0, parent, 0, type, &COMPILE_OPTION_DEFAULT, Qnil); } static int -ast_line_count(const rb_ast_body_t *ast) +ast_line_count(const VALUE vast) { - if (ast->script_lines == NULL) { + rb_ast_t *ast = rb_ruby_ast_data_get(vast); + if (!ast || !ast->body.script_lines) { // this occurs when failed to parse the source code with a syntax error return 0; } - if (!FIXNUM_P((VALUE)ast->script_lines)) { - return (int)ast->script_lines->len; + if (!FIXNUM_P((VALUE)ast->body.script_lines)) { + return (int)ast->body.script_lines->len; } - return FIX2INT((VALUE)ast->script_lines); + return FIX2INT((VALUE)ast->body.script_lines); } static VALUE -iseq_setup_coverage(VALUE coverages, VALUE path, const rb_ast_body_t *ast, int line_offset) +iseq_setup_coverage(VALUE coverages, VALUE path, const VALUE vast, int line_offset) { - int line_count = line_offset + ast_line_count(ast); + int line_count = line_offset + ast_line_count(vast); if (line_count >= 0) { int len = (rb_get_coverage_mode() & COVERAGE_TARGET_ONESHOT_LINES) ? 0 : line_count; @@ -878,21 +879,21 @@ iseq_setup_coverage(VALUE coverages, VALUE path, const rb_ast_body_t *ast, int l } static inline void -iseq_new_setup_coverage(VALUE path, const rb_ast_body_t *ast, int line_offset) +iseq_new_setup_coverage(VALUE path, const VALUE vast, int line_offset) { VALUE coverages = rb_get_coverages(); if (RTEST(coverages)) { - iseq_setup_coverage(coverages, path, ast, line_offset); + iseq_setup_coverage(coverages, path, vast, line_offset); } } rb_iseq_t * -rb_iseq_new_top(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent) +rb_iseq_new_top(const VALUE vast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent) { - iseq_new_setup_coverage(path, ast, 0); + iseq_new_setup_coverage(path, vast, 0); - return rb_iseq_new_with_opt(ast, name, path, realpath, 0, parent, 0, + return rb_iseq_new_with_opt(vast, name, path, realpath, 0, parent, 0, ISEQ_TYPE_TOP, &COMPILE_OPTION_DEFAULT, Qnil); } @@ -910,11 +911,11 @@ pm_iseq_new_top(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath, c } rb_iseq_t * -rb_iseq_new_main(const rb_ast_body_t *ast, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt) +rb_iseq_new_main(const VALUE vast, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt) { - iseq_new_setup_coverage(path, ast, 0); + iseq_new_setup_coverage(path, vast, 0); - return rb_iseq_new_with_opt(ast, rb_fstring_lit("<main>"), + return rb_iseq_new_with_opt(vast, rb_fstring_lit("<main>"), path, realpath, 0, parent, 0, ISEQ_TYPE_MAIN, opt ? &COMPILE_OPTION_DEFAULT : &COMPILE_OPTION_FALSE, Qnil); @@ -935,16 +936,16 @@ pm_iseq_new_main(pm_scope_node_t *node, VALUE path, VALUE realpath, const rb_ise } 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) +rb_iseq_new_eval(const VALUE vast, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_iseq_t *parent, int isolated_depth) { if (rb_get_coverage_mode() & COVERAGE_TARGET_EVAL) { VALUE coverages = rb_get_coverages(); if (RTEST(coverages) && RTEST(path) && !RTEST(rb_hash_has_key(coverages, path))) { - iseq_setup_coverage(coverages, path, ast, first_lineno - 1); + iseq_setup_coverage(coverages, path, vast, first_lineno - 1); } } - return rb_iseq_new_with_opt(ast, name, path, realpath, first_lineno, + return rb_iseq_new_with_opt(vast, name, path, realpath, first_lineno, parent, isolated_depth, ISEQ_TYPE_EVAL, &COMPILE_OPTION_DEFAULT, Qnil); } @@ -972,27 +973,29 @@ iseq_translate(rb_iseq_t *iseq) } rb_iseq_t * -rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, +rb_iseq_new_with_opt(const VALUE vast, 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, VALUE script_lines) { - const NODE *node = ast ? ast->root : 0; + rb_ast_t *ast = rb_ruby_ast_data_get(vast); + rb_ast_body_t *body = ast ? &ast->body : NULL; + const NODE *node = body ? body->root : 0; /* TODO: argument check */ rb_iseq_t *iseq = iseq_alloc(); rb_compile_option_t new_opt; if (!option) option = &COMPILE_OPTION_DEFAULT; - if (ast) { + if (body) { new_opt = *option; - option = set_compile_option_from_ast(&new_opt, ast); + option = set_compile_option_from_ast(&new_opt, body); } if (!NIL_P(script_lines)) { // noop } - else if (ast && !FIXNUM_P((VALUE)ast->script_lines) && ast->script_lines) { - script_lines = rb_parser_build_script_lines_from(ast->script_lines); + else if (body && !FIXNUM_P((VALUE)body->script_lines) && body->script_lines) { + script_lines = rb_parser_build_script_lines_from(body->script_lines); } else if (parent) { script_lines = ISEQ_BODY(parent)->variable.script_lines; @@ -1214,9 +1217,10 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, V #else # define INITIALIZED /* volatile */ #endif - rb_ast_t *(*parse)(VALUE vparser, VALUE fname, VALUE file, int start); + VALUE (*parse)(VALUE vparser, VALUE fname, VALUE file, int start); int ln; - rb_ast_t *INITIALIZED ast; + VALUE INITIALIZED vast; + rb_ast_t *ast; VALUE name = rb_fstring_lit("<compiled>"); /* safe results first */ @@ -1232,20 +1236,22 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, V } { const VALUE parser = rb_parser_new(); - const rb_iseq_t *outer_scope = rb_iseq_new(NULL, name, name, Qnil, 0, ISEQ_TYPE_TOP); + const rb_iseq_t *outer_scope = rb_iseq_new(Qnil, name, name, Qnil, 0, ISEQ_TYPE_TOP); VALUE outer_scope_v = (VALUE)outer_scope; rb_parser_set_context(parser, outer_scope, FALSE); if (ruby_vm_keep_script_lines) rb_parser_set_script_lines(parser); RB_GC_GUARD(outer_scope_v); - ast = (*parse)(parser, file, src, ln); + vast = (*parse)(parser, file, src, ln); } - if (!ast->body.root) { + ast = rb_ruby_ast_data_get(vast); + + if (!ast || !ast->body.root) { rb_ast_dispose(ast); rb_exc_raise(GET_EC()->errinfo); } else { - iseq = rb_iseq_new_with_opt(&ast->body, name, file, realpath, ln, + iseq = rb_iseq_new_with_opt(vast, name, file, realpath, ln, NULL, 0, ISEQ_TYPE_TOP, &option, Qnil); rb_ast_dispose(ast); @@ -1606,6 +1612,7 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self) VALUE file, opt = Qnil; VALUE parser, f, exc = Qnil, ret; rb_ast_t *ast; + VALUE vast; rb_compile_option_t option; int i; @@ -1624,7 +1631,8 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self) parser = rb_parser_new(); rb_parser_set_context(parser, NULL, FALSE); - ast = (rb_ast_t *)rb_parser_load_file(parser, file); + vast = rb_parser_load_file(parser, file); + ast = rb_ruby_ast_data_get(vast); if (!ast->body.root) exc = GET_EC()->errinfo; rb_io_close(f); @@ -1635,7 +1643,7 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self) make_compile_option(&option, opt); - ret = iseqw_new(rb_iseq_new_with_opt(&ast->body, rb_fstring_lit("<main>"), + ret = iseqw_new(rb_iseq_new_with_opt(vast, rb_fstring_lit("<main>"), file, rb_realpath_internal(Qnil, file, 1), 1, NULL, 0, ISEQ_TYPE_TOP, &option, @@ -762,11 +762,13 @@ load_iseq_eval(rb_execution_context_t *ec, VALUE fname) } else { rb_ast_t *ast; + VALUE vast; VALUE parser = rb_parser_new(); rb_parser_set_context(parser, NULL, FALSE); - ast = (rb_ast_t *)rb_parser_load_file(parser, fname); + vast = rb_parser_load_file(parser, fname); + ast = rb_ruby_ast_data_get(vast); - iseq = rb_iseq_new_top(&ast->body, rb_fstring_lit("<top (required)>"), + iseq = rb_iseq_new_top(vast, rb_fstring_lit("<top (required)>"), fname, realpath_internal_cached(realpath_map, fname), NULL); rb_ast_dispose(ast); } diff --git a/mini_builtin.c b/mini_builtin.c index 38b0ca8d81..b38642e89b 100644 --- a/mini_builtin.c +++ b/mini_builtin.c @@ -12,16 +12,17 @@ static struct st_table *loaded_builtin_table; #endif -rb_ast_t *rb_builtin_ast(const char *feature_name, VALUE *name_str); +VALUE rb_builtin_vast(const char *feature_name, VALUE *name_str); static const rb_iseq_t * builtin_iseq_load(const char *feature_name, const struct rb_builtin_function *table) { VALUE name_str = 0; - rb_ast_t *ast = rb_builtin_ast(feature_name, &name_str); + rb_ast_t *ast; + VALUE vast = rb_builtin_vast(feature_name, &name_str); rb_vm_t *vm = GET_VM(); - if (!ast) { + if (NIL_P(vast)) { rb_fatal("builtin_iseq_load: can not find %s; " "probably miniprelude.c is out of date", feature_name); @@ -39,7 +40,8 @@ builtin_iseq_load(const char *feature_name, const struct rb_builtin_function *ta .coverage_enabled = FALSE, .debug_level = 0, }; - const rb_iseq_t *iseq = rb_iseq_new_with_opt(&ast->body, name_str, name_str, Qnil, 0, NULL, 0, ISEQ_TYPE_TOP, &optimization, Qnil); + ast = rb_ruby_ast_data_get(vast); + const rb_iseq_t *iseq = rb_iseq_new_with_opt(vast, name_str, name_str, Qnil, 0, NULL, 0, ISEQ_TYPE_TOP, &optimization, Qnil); GET_VM()->builtin_function_table = NULL; rb_ast_dispose(ast); @@ -304,14 +304,16 @@ rb_ast_t * rb_ast_new(const rb_parser_config_t *config) { node_buffer_t *nb = rb_node_buffer_new(config); - return config->ast_new((VALUE)nb); + return config->ast_new(nb); } #else rb_ast_t * rb_ast_new(void) { node_buffer_t *nb = rb_node_buffer_new(); - return IMEMO_NEW(rb_ast_t, imemo_ast, (VALUE)nb); + rb_ast_t *ast = ruby_xcalloc(1, sizeof(rb_ast_t)); + ast->node_buffer = nb; + return ast; } #endif @@ -348,14 +350,26 @@ script_lines_free(rb_ast_t *ast, rb_parser_ary_t *script_lines) void rb_ast_free(rb_ast_t *ast) { - if (ast->node_buffer) { + /* TODO + * The current impl. of rb_ast_free() and rb_ast_dispose() is complicated. + * Upcoming task of changing `ast->node_buffer->config` to `ast->config`, + * that is based on "deIMEMO" of `rb_ast_t *`, will let us simplify the code. + */ +#ifdef UNIVERSAL_PARSER + if (ast && ast->node_buffer) { + void (*free_func)(void *) = xfree; if (ast->body.script_lines && !FIXNUM_P((VALUE)ast->body.script_lines)) { script_lines_free(ast, ast->body.script_lines); ast->body.script_lines = NULL; } rb_node_buffer_free(ast, ast->node_buffer); ast->node_buffer = 0; + free_func(ast); } +#else + rb_ast_dispose(ast); + xfree(ast); +#endif } static size_t @@ -373,20 +387,63 @@ buffer_list_size(node_buffer_list_t *nb) size_t rb_ast_memsize(const rb_ast_t *ast) { - size_t size = 0; + size_t size = sizeof(rb_ast_t); node_buffer_t *nb = ast->node_buffer; + rb_parser_ary_t *tokens = NULL; + struct rb_ast_local_table_link *link = NULL; + rb_parser_ary_t *script_lines = ast->body.script_lines; + + long i; if (nb) { size += sizeof(node_buffer_t); size += buffer_list_size(&nb->buffer_list); + link = nb->local_tables; + tokens = nb->tokens; + } + + while (link) { + size += sizeof(struct rb_ast_local_table_link); + size += link->size * sizeof(ID); + link = link->next; + } + + if (tokens) { + size += sizeof(rb_parser_ary_t); + for (i = 0; i < tokens->len; i++) { + size += sizeof(rb_parser_ast_token_t); + rb_parser_ast_token_t *token = tokens->data[i]; + size += sizeof(rb_parser_string_t); + size += token->str->len + 1; + } + } + + if (script_lines && !FIXNUM_P((VALUE)script_lines)) { + size += sizeof(rb_parser_ary_t); + for (i = 0; i < script_lines->len; i++) { + size += sizeof(rb_parser_string_t); + size += ((rb_parser_string_t *)script_lines->data[i])->len + 1; + } } + return size; } void rb_ast_dispose(rb_ast_t *ast) { - rb_ast_free(ast); +#ifdef UNIVERSAL_PARSER + // noop. See the comment in rb_ast_free(). +#else + if (ast && ast->node_buffer) { + if (ast->body.script_lines && !FIXNUM_P((VALUE)ast->body.script_lines)) { + script_lines_free(ast, ast->body.script_lines); + ast->body.script_lines = NULL; + } + rb_node_buffer_free(ast, ast->node_buffer); + ast->node_buffer = 0; + } +#endif } VALUE @@ -15809,7 +15809,6 @@ rb_ruby_parser_mark(void *ptr) struct parser_params *p = (struct parser_params*)ptr; rb_gc_mark(p->ruby_sourcefile_string); - rb_gc_mark((VALUE)p->ast); #ifndef RIPPER rb_gc_mark(p->error_buffer); #else @@ -3467,7 +3467,7 @@ proc_binding(VALUE self) env = VM_ENV_ENVVAL_PTR(block->as.captured.ep); env = env_clone(env, method_cref(method)); /* set empty iseq */ - empty = rb_iseq_new(NULL, name, name, Qnil, 0, ISEQ_TYPE_TOP); + empty = rb_iseq_new(Qnil, name, name, Qnil, 0, ISEQ_TYPE_TOP); RB_OBJ_WRITE(env, &env->iseq, empty); break; } @@ -225,7 +225,7 @@ cmdline_options_init(ruby_cmdline_options_t *opt) return opt; } -static rb_ast_t *load_file(VALUE parser, VALUE fname, VALUE f, int script, +static VALUE load_file(VALUE parser, VALUE fname, VALUE f, int script, ruby_cmdline_options_t *opt); static VALUE open_load_file(VALUE fname_v, int *xflag); static void forbid_setid(const char *, const ruby_cmdline_options_t *); @@ -2056,10 +2056,11 @@ show_help(const char *progname, int help) usage(progname, help, tty, columns); } -static rb_ast_t * +static VALUE process_script(ruby_cmdline_options_t *opt) { rb_ast_t *ast; + VALUE vast; VALUE parser = rb_parser_new(); const unsigned int dump = opt->dump; @@ -2079,7 +2080,7 @@ process_script(ruby_cmdline_options_t *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); + vast = rb_parser_compile_string(parser, opt->script, opt->e_script, 1); } else { VALUE f; @@ -2087,13 +2088,14 @@ process_script(ruby_cmdline_options_t *opt) f = open_load_file(opt->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); + vast = load_file(parser, opt->script_name, f, 1, opt); } + ast = rb_ruby_ast_data_get(vast); if (!ast->body.root) { rb_ast_dispose(ast); - return NULL; + return Qnil; } - return ast; + return vast; } /** @@ -2237,6 +2239,7 @@ process_options_global_setup(const ruby_cmdline_options_t *opt, const rb_iseq_t static VALUE process_options(int argc, char **argv, ruby_cmdline_options_t *opt) { + VALUE vast = Qnil; struct { rb_ast_t *ast; pm_parse_result_t prism; @@ -2471,7 +2474,8 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) } if (!(*rb_ruby_prism_ptr())) { - if (!(result.ast = process_script(opt))) return Qfalse; + vast = process_script(opt); + if (!(result.ast = rb_ruby_ast_data_get(vast))) return Qfalse; } else { prism_script(opt, &result.prism); @@ -2553,7 +2557,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) } else { rb_ast_t *ast = result.ast; - iseq = rb_iseq_new_main(&ast->body, opt->script_name, path, parent, optimize); + iseq = rb_iseq_new_main(vast, opt->script_name, path, parent, optimize); rb_ast_dispose(ast); } } @@ -2604,7 +2608,7 @@ load_file_internal(VALUE argp_v) ruby_cmdline_options_t *opt = argp->opt; VALUE f = argp->f; int line_start = 1; - rb_ast_t *ast = 0; + VALUE vast = Qnil; rb_encoding *enc; ID set_encoding; @@ -2702,10 +2706,10 @@ load_file_internal(VALUE argp_v) if (NIL_P(f)) { f = rb_str_new(0, 0); rb_enc_associate(f, enc); - return (VALUE)rb_parser_compile_string_path(parser, orig_fname, f, line_start); + return rb_parser_compile_string_path(parser, orig_fname, f, line_start); } rb_funcall(f, set_encoding, 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-")); - ast = rb_parser_compile_file_path(parser, orig_fname, f, line_start); + vast = rb_parser_compile_file_path(parser, orig_fname, f, line_start); rb_funcall(f, set_encoding, 1, rb_parser_encoding(parser)); if (script && rb_parser_end_seen_p(parser)) { /* @@ -2723,7 +2727,7 @@ load_file_internal(VALUE argp_v) rb_define_global_const("DATA", f); argp->f = Qnil; } - return (VALUE)ast; + return vast; } /* disabling O_NONBLOCK, and returns 0 on success, otherwise errno */ @@ -2832,7 +2836,7 @@ restore_load_file(VALUE arg) return Qnil; } -static rb_ast_t * +static VALUE load_file(VALUE parser, VALUE fname, VALUE f, int script, ruby_cmdline_options_t *opt) { struct load_file_arg arg; @@ -2841,7 +2845,7 @@ load_file(VALUE parser, VALUE fname, VALUE f, int script, ruby_cmdline_options_t arg.script = script; arg.opt = opt; arg.f = f; - return (rb_ast_t *)rb_ensure(load_file_internal, (VALUE)&arg, + return rb_ensure(load_file_internal, (VALUE)&arg, restore_load_file, (VALUE)&arg); } @@ -2855,10 +2859,12 @@ rb_load_file(const char *fname) void * rb_load_file_str(VALUE fname_v) { - return rb_parser_load_file(rb_parser_new(), fname_v); + VALUE vast; + vast = rb_parser_load_file(rb_parser_new(), fname_v); + return (void *)rb_ruby_ast_data_get(vast); } -void * +VALUE rb_parser_load_file(VALUE parser, VALUE fname_v) { ruby_cmdline_options_t opt; diff --git a/ruby_parser.c b/ruby_parser.c index decc05f619..7ba5c26fb0 100644 --- a/ruby_parser.c +++ b/ruby_parser.c @@ -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; +} diff --git a/rubyparser.h b/rubyparser.h index d83f9ac3f4..55a49a2b32 100644 --- a/rubyparser.h +++ b/rubyparser.h @@ -1208,7 +1208,7 @@ typedef struct RNode_ERROR { (n)->flags=(((n)->flags&~NODE_TYPEMASK)|((((unsigned long)(t))<<NODE_TYPESHIFT)&NODE_TYPEMASK)) typedef struct node_buffer_struct node_buffer_t; -/* T_IMEMO/ast */ + typedef struct rb_ast_body_struct { const NODE *root; rb_parser_ary_t *script_lines; @@ -1219,7 +1219,6 @@ typedef struct rb_ast_body_struct { signed int coverage_enabled:2; /* -1: not specified, 0: false, 1: true */ } rb_ast_body_t; typedef struct rb_ast_struct { - VALUE flags; node_buffer_t *node_buffer; rb_ast_body_t body; } rb_ast_t; @@ -1251,8 +1250,7 @@ typedef struct rb_parser_config_struct { void *(*nonempty_memcpy)(void *dest, const void *src, size_t t, size_t n); void *(*xmalloc_mul_add)(size_t x, size_t y, size_t z); - /* imemo */ - rb_ast_t *(*ast_new)(VALUE nb); + rb_ast_t *(*ast_new)(node_buffer_t *nb); // VALUE rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg); VALUE (*compile_callback)(VALUE (*func)(VALUE), VALUE arg); diff --git a/template/prelude.c.tmpl b/template/prelude.c.tmpl index dc0a143004..386511f20c 100644 --- a/template/prelude.c.tmpl +++ b/template/prelude.c.tmpl @@ -141,37 +141,39 @@ COMPILER_WARNING_POP #define PRELUDE_NAME(n) rb_usascii_str_new_static(prelude_name##n, sizeof(prelude_name##n)-1) #define PRELUDE_CODE(n) rb_utf8_str_new_static(prelude_code##n.L0, sizeof(prelude_code##n)) -static rb_ast_t * -prelude_ast(VALUE name, VALUE code, int line) +static VALUE +prelude_vast(VALUE name, VALUE code, int line) { - rb_ast_t *ast = rb_parser_compile_string_path(rb_parser_new(), name, code, line); + rb_ast_t *ast; + VALUE vast = rb_parser_compile_string_path(rb_parser_new(), name, code, line); + ast = rb_ruby_ast_data_get(vast); if (!ast || !ast->body.root) { if (ast) rb_ast_dispose(ast); rb_exc_raise(rb_errinfo()); } - return ast; + return vast; } % end % if @builtin_count > 0 -#define PRELUDE_AST(n, name_str, start_line) \ +#define PRELUDE_VAST(n, name_str, start_line) \ (((sizeof(prelude_name<%='##'%><%=%>n) - prefix_len - 2) == namelen) && \ (strncmp(prelude_name<%='##'%><%=%>n + prefix_len, feature_name, namelen) == 0) ? \ - prelude_ast((name_str) = PRELUDE_NAME(n), PRELUDE_CODE(n), start_line) : 0) + prelude_vast((name_str) = PRELUDE_NAME(n), PRELUDE_CODE(n), start_line) : Qnil) -rb_ast_t * -rb_builtin_ast(const char *feature_name, VALUE *name_str) +VALUE +rb_builtin_vast(const char *feature_name, VALUE *name_str) { const size_t prefix_len = rb_strlen_lit("<internal:"); size_t namelen = strlen(feature_name); - rb_ast_t *ast = 0; + VALUE vast = Qnil; % @preludes.each_value do |i, prelude, lines, sub, start_line| % if sub - if ((ast = PRELUDE_AST(<%=i%><%=%>, *name_str, <%=start_line%>)) != 0) return ast; + if (!NIL_P(vast = PRELUDE_VAST(<%=i%><%=%>, *name_str, <%=start_line%>))) return vast; % end % end - return ast; + return vast; } % end @@ -196,8 +198,10 @@ prelude_eval(VALUE code, VALUE name, int line) 0, /* int debug_level; */ }; - rb_ast_t *ast = prelude_ast(name, code, line); - rb_iseq_eval(rb_iseq_new_with_opt(&ast->body, name, name, Qnil, line, + rb_ast_t *ast; + VALUE vast = prelude_vast(name, code, line); + ast = rb_ruby_ast_data_get(vast); + rb_iseq_eval(rb_iseq_new_with_opt(vast, name, name, Qnil, line, NULL, 0, ISEQ_TYPE_TOP, &optimization, Qnil)); rb_ast_dispose(ast); @@ -1463,7 +1463,6 @@ rb_binding_add_dynavars(VALUE bindval, rb_binding_t *bind, int dyncount, const I const rb_env_t *env; rb_execution_context_t *ec = GET_EC(); const rb_iseq_t *base_iseq, *iseq; - rb_ast_body_t ast; rb_node_scope_t tmp_node; if (dyncount < 0) return 0; @@ -1481,17 +1480,14 @@ rb_binding_add_dynavars(VALUE bindval, rb_binding_t *bind, int dyncount, const I tmp_node.nd_body = 0; tmp_node.nd_args = 0; - ast.root = RNODE(&tmp_node); - ast.frozen_string_literal = -1; - ast.coverage_enabled = -1; - ast.script_lines = (rb_parser_ary_t *)INT2FIX(-1); + VALUE vast = rb_ruby_ast_new(RNODE(&tmp_node), (rb_parser_ary_t *)INT2FIX(-1)); if (base_iseq) { - iseq = rb_iseq_new(&ast, ISEQ_BODY(base_iseq)->location.label, path, realpath, base_iseq, ISEQ_TYPE_EVAL); + iseq = rb_iseq_new(vast, ISEQ_BODY(base_iseq)->location.label, path, realpath, base_iseq, ISEQ_TYPE_EVAL); } else { VALUE tempstr = rb_fstring_lit("<temp>"); - iseq = rb_iseq_new_top(&ast, tempstr, tempstr, tempstr, NULL); + iseq = rb_iseq_new_top(vast, tempstr, tempstr, tempstr, NULL); } tmp_node.nd_tbl = 0; /* reset table */ ALLOCV_END(idtmp); @@ -2864,7 +2860,7 @@ rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, { rb_execution_context_t *ec = GET_EC(); const rb_control_frame_t *reg_cfp = ec->cfp; - const rb_iseq_t *iseq = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP); + const rb_iseq_t *iseq = rb_iseq_new(Qnil, filename, filename, Qnil, 0, ISEQ_TYPE_TOP); VALUE val; vm_push_frame(ec, iseq, VM_FRAME_MAGIC_TOP | VM_ENV_FLAG_LOCAL | VM_FRAME_FLAG_FINISH, @@ -4179,7 +4175,7 @@ Init_VM(void) rb_vm_t *vm = ruby_current_vm_ptr; rb_thread_t *th = GET_THREAD(); VALUE filename = rb_fstring_lit("<main>"); - const rb_iseq_t *iseq = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP); + const rb_iseq_t *iseq = rb_iseq_new(Qnil, filename, filename, Qnil, 0, ISEQ_TYPE_TOP); // Ractor setup rb_ractor_main_setup(vm, th->ractor, th); @@ -1209,11 +1209,11 @@ typedef enum { RUBY_SYMBOL_EXPORT_BEGIN /* node -> iseq */ -rb_iseq_t *rb_iseq_new (const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, enum rb_iseq_type); -rb_iseq_t *rb_iseq_new_top (const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent); -rb_iseq_t *rb_iseq_new_main (const rb_ast_body_t *ast, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt); -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); -rb_iseq_t *rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_iseq_t *parent, int isolated_depth, +rb_iseq_t *rb_iseq_new (const VALUE vast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, enum rb_iseq_type); +rb_iseq_t *rb_iseq_new_top (const VALUE vast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent); +rb_iseq_t *rb_iseq_new_main (const VALUE vast, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt); +rb_iseq_t *rb_iseq_new_eval (const VALUE vast, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_iseq_t *parent, int isolated_depth); +rb_iseq_t *rb_iseq_new_with_opt(const VALUE vast, 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 script_lines); @@ -1753,6 +1753,7 @@ eval_make_iseq(VALUE src, VALUE fname, int line, const VALUE parser = rb_parser_new(); const rb_iseq_t *const parent = vm_block_iseq(base_block); rb_iseq_t *iseq = NULL; + VALUE vast; rb_ast_t *ast; int isolated_depth = 0; @@ -1790,10 +1791,13 @@ eval_make_iseq(VALUE src, VALUE fname, int line, rb_parser_set_context(parser, parent, FALSE); if (ruby_vm_keep_script_lines) rb_parser_set_script_lines(parser); - ast = rb_parser_compile_string_path(parser, fname, src, line); + vast = rb_parser_compile_string_path(parser, fname, src, line); + + ast = rb_ruby_ast_data_get(vast); + if (ast->body.root) { ast->body.coverage_enabled = coverage_enabled; - iseq = rb_iseq_new_eval(&ast->body, + iseq = rb_iseq_new_eval(vast, ISEQ_BODY(parent)->location.label, fname, Qnil, line, parent, isolated_depth); |