From ccd45a1399a9eed7c59120874d0d37bd3ce9d73d Mon Sep 17 00:00:00 2001 From: yui-knk Date: Sat, 13 Jan 2024 13:54:13 +0900 Subject: [PATCH] Stop using Array to manage dummy `end` token locations Before this commit, Array is used to store token locations which expect `end` token, e.g. `class` and `module`. This commit introduces dedicated struct to manage them so that dependency on Ruby Object is reduced. --- parse.y | 63 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/parse.y b/parse.y index 568a8c27e7..339efb3297 100644 --- a/parse.y +++ b/parse.y @@ -527,6 +527,11 @@ typedef struct token_info { struct token_info *next; } token_info; +typedef struct end_expect_token_locations { + const rb_code_position_t *pos; + struct end_expect_token_locations *prev; +} end_expect_token_locations_t; + /* Structure of Lexer Buffer: @@ -639,8 +644,11 @@ struct parser_params { VALUE error_buffer; VALUE debug_lines; const struct rb_iseq_struct *parent_iseq; - /* store specific keyword locations to generate dummy end token */ - VALUE end_expect_token_locations; + /* + * Store specific keyword locations to generate dummy end token. + * Refer to the tail of list element. + */ + end_expect_token_locations_t *end_expect_token_locations; /* id for terms */ int token_id; /* Array for term tokens */ @@ -703,8 +711,15 @@ static void debug_end_expect_token_locations(struct parser_params *p, const char *name) { if(p->debug) { - VALUE mesg = rb_sprintf("%s: ", name); - rb_str_catf(mesg, " %"PRIsVALUE"\n", p->end_expect_token_locations); + VALUE mesg = rb_sprintf("%s: [", name); + int i = 0; + for (end_expect_token_locations_t *loc = p->end_expect_token_locations; loc; loc = loc->prev) { + if (i > 0) + rb_str_cat_cstr(mesg, ", "); + rb_str_catf(mesg, "[%d, %d]", loc->pos->lineno, loc->pos->column); + i++; + } + rb_str_cat_cstr(mesg, "]\n"); flush_debug_buffer(p, p->debug_output, mesg); } } @@ -712,24 +727,33 @@ debug_end_expect_token_locations(struct parser_params *p, const char *name) static void push_end_expect_token_locations(struct parser_params *p, const rb_code_position_t *pos) { - if(NIL_P(p->end_expect_token_locations)) return; - rb_ary_push(p->end_expect_token_locations, rb_ary_new_from_args(2, INT2NUM(pos->lineno), INT2NUM(pos->column))); + if(!p->error_tolerant) return; + + end_expect_token_locations_t *locations; + locations = ALLOC(end_expect_token_locations_t); + locations->pos = pos; + locations->prev = p->end_expect_token_locations; + p->end_expect_token_locations = locations; + debug_end_expect_token_locations(p, "push_end_expect_token_locations"); } static void pop_end_expect_token_locations(struct parser_params *p) { - if(NIL_P(p->end_expect_token_locations)) return; - rb_ary_pop(p->end_expect_token_locations); + if(!p->end_expect_token_locations) return; + + end_expect_token_locations_t *locations = p->end_expect_token_locations->prev; + ruby_sized_xfree(p->end_expect_token_locations, sizeof(end_expect_token_locations_t)); + p->end_expect_token_locations = locations; + debug_end_expect_token_locations(p, "pop_end_expect_token_locations"); } -static VALUE +static end_expect_token_locations_t * peek_end_expect_token_locations(struct parser_params *p) { - if(NIL_P(p->end_expect_token_locations)) return Qnil; - return rb_ary_last(0, 0, p->end_expect_token_locations); + return p->end_expect_token_locations; } static ID @@ -10560,14 +10584,14 @@ parse_ident(struct parser_params *p, int c, int cmd_state) } #ifndef RIPPER - if (!NIL_P(peek_end_expect_token_locations(p))) { - VALUE end_loc; + if (peek_end_expect_token_locations(p)) { + const rb_code_position_t *end_pos; int lineno, column; int beg_pos = (int)(p->lex.ptok - p->lex.pbeg); - end_loc = peek_end_expect_token_locations(p); - lineno = NUM2INT(rb_ary_entry(end_loc, 0)); - column = NUM2INT(rb_ary_entry(end_loc, 1)); + end_pos = peek_end_expect_token_locations(p)->pos; + lineno = end_pos->lineno; + column = end_pos->column; if (p->debug) { rb_parser_printf(p, "enforce_keyword_end check. current: (%d, %d), peek: (%d, %d)\n", @@ -10692,7 +10716,7 @@ parser_yylex(struct parser_params *p) case -1: /* end of script. */ p->eofp = 1; #ifndef RIPPER - if (!NIL_P(p->end_expect_token_locations) && RARRAY_LEN(p->end_expect_token_locations) > 0) { + if (p->end_expect_token_locations) { pop_end_expect_token_locations(p); RUBY_SET_YYLLOC_OF_DUMMY_END(*p->yylloc); return tDUMNY_END; @@ -15856,7 +15880,7 @@ parser_initialize(struct parser_params *p) p->parsing_thread = Qnil; #else p->error_buffer = Qfalse; - p->end_expect_token_locations = Qnil; + p->end_expect_token_locations = NULL; p->token_id = 0; p->tokens = Qnil; #endif @@ -15887,7 +15911,6 @@ rb_ruby_parser_mark(void *ptr) #ifndef RIPPER rb_gc_mark(p->debug_lines); rb_gc_mark(p->error_buffer); - rb_gc_mark(p->end_expect_token_locations); rb_gc_mark(p->tokens); #else rb_gc_mark(p->value); @@ -16012,8 +16035,6 @@ void rb_ruby_parser_error_tolerant(rb_parser_t *p) { p->error_tolerant = 1; - // TODO - p->end_expect_token_locations = rb_ary_new(); } void