diff options
Diffstat (limited to 'yarp/yarp_compiler.c')
-rw-r--r-- | yarp/yarp_compiler.c | 204 |
1 files changed, 114 insertions, 90 deletions
diff --git a/yarp/yarp_compiler.c b/yarp/yarp_compiler.c index 7157c2b9fa..fa71c12226 100644 --- a/yarp/yarp_compiler.c +++ b/yarp/yarp_compiler.c @@ -197,26 +197,7 @@ again: } static void -yp_compile_if(rb_iseq_t *iseq, const yp_node_t *node, LINK_ANCHOR *const ret, const char * src, bool popped, yp_compile_context_t *compile_context) { - yp_parser_t *parser = compile_context->parser; - yp_statements_node_t *node_body; - yp_node_t *node_else; - yp_node_t *predicate; - - if (node->type == YP_NODE_IF_NODE) { - yp_if_node_t *if_node = (yp_if_node_t *)node; - node_body = if_node->statements; - node_else = if_node->consequent; - predicate = if_node->predicate; - } - else { - yp_unless_node_t *unless_node = (yp_unless_node_t *)node; - node_body = unless_node->statements; - node_else = (yp_node_t *)(unless_node->consequent); - predicate = unless_node->predicate; - } - - const int line = (int)yp_newline_list_line_column(&(parser->newline_list), node->location.start).line; +yp_compile_if(rb_iseq_t *iseq, const int line, yp_statements_node_t *node_body, yp_node_t *node_else, yp_node_t *predicate, LINK_ANCHOR *const ret, const char * src, bool popped, yp_compile_context_t *compile_context) { NODE line_node = generate_dummy_line_node(line, line); DECL_ANCHOR(cond_seq); @@ -279,6 +260,84 @@ yp_compile_if(rb_iseq_t *iseq, const yp_node_t *node, LINK_ANCHOR *const ret, co return; } +static void +yp_compile_while(rb_iseq_t *iseq, int lineno, yp_node_flags_t flags, enum yp_node_type type, yp_statements_node_t *statements, yp_node_t *predicate, LINK_ANCHOR *const ret, const char * src, bool popped, yp_compile_context_t *compile_context) +{ + NODE dummy_line_node = generate_dummy_line_node(lineno, lineno); + + LABEL *prev_start_label = ISEQ_COMPILE_DATA(iseq)->start_label; + LABEL *prev_end_label = ISEQ_COMPILE_DATA(iseq)->end_label; + LABEL *prev_redo_label = ISEQ_COMPILE_DATA(iseq)->redo_label; + int prev_loopval_popped = ISEQ_COMPILE_DATA(iseq)->loopval_popped; + + // TODO: Deal with ensures in here + LABEL *next_label = ISEQ_COMPILE_DATA(iseq)->start_label = NEW_LABEL(lineno); /* next */ + LABEL *redo_label = ISEQ_COMPILE_DATA(iseq)->redo_label = NEW_LABEL(lineno); /* redo */ + LABEL *break_label = ISEQ_COMPILE_DATA(iseq)->end_label = NEW_LABEL(lineno); /* break */ + LABEL *end_label = NEW_LABEL(lineno); + LABEL *adjust_label = NEW_LABEL(lineno); + + LABEL *next_catch_label = NEW_LABEL(lineno); + LABEL *tmp_label = NULL; + + ISEQ_COMPILE_DATA(iseq)->loopval_popped = 0; + + // begin; end while true + if (flags & YP_LOOP_FLAGS_BEGIN_MODIFIER) { + ADD_INSNL(ret, &dummy_line_node, jump, next_label); + } + else { + // while true; end + tmp_label = NEW_LABEL(lineno); + ADD_INSNL(ret, &dummy_line_node, jump, tmp_label); + } + + ADD_LABEL(ret, adjust_label); + ADD_INSN(ret, &dummy_line_node, putnil); + ADD_LABEL(ret, next_catch_label); + ADD_INSN(ret, &dummy_line_node, pop); + ADD_INSNL(ret, &dummy_line_node, jump, next_label); + if (tmp_label) ADD_LABEL(ret, tmp_label); + + ADD_LABEL(ret, redo_label); + if (statements) { + yp_compile_node(iseq, (yp_node_t *)statements, ret, src, Qtrue, compile_context); + } + + ADD_LABEL(ret, next_label); + + if (type == YP_NODE_WHILE_NODE) { + yp_compile_branch_condition(iseq, ret, predicate, redo_label, end_label, src, popped, compile_context); + } + else if (type == YP_NODE_UNTIL_NODE) { + yp_compile_branch_condition(iseq, ret, predicate, end_label, redo_label, src, popped, compile_context); + } + + ADD_LABEL(ret, end_label); + ADD_ADJUST_RESTORE(ret, adjust_label); + + ADD_INSN(ret, &dummy_line_node, putnil); + + ADD_LABEL(ret, break_label); + + if (popped) { + ADD_INSN(ret, &dummy_line_node, pop); + } + + ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, redo_label, break_label, NULL, + break_label); + ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, redo_label, break_label, NULL, + next_catch_label); + ADD_CATCH_ENTRY(CATCH_TYPE_REDO, redo_label, break_label, NULL, + ISEQ_COMPILE_DATA(iseq)->redo_label); + + ISEQ_COMPILE_DATA(iseq)->start_label = prev_start_label; + ISEQ_COMPILE_DATA(iseq)->end_label = prev_end_label; + ISEQ_COMPILE_DATA(iseq)->redo_label = prev_redo_label; + ISEQ_COMPILE_DATA(iseq)->loopval_popped = prev_loopval_popped; + return; +} + static rb_iseq_t * yp_new_child_iseq(rb_iseq_t *iseq, yp_scope_node_t * node, yp_parser_t *parser, VALUE name, const rb_iseq_t *parent, enum rb_iseq_type type, int line_no) @@ -329,7 +388,8 @@ yp_compile_class_path(LINK_ANCHOR *const ret, rb_iseq_t *iseq, const yp_node_t * * compile_context - Stores parser and local information */ static void -yp_compile_node(rb_iseq_t *iseq, const yp_node_t *node, LINK_ANCHOR *const ret, const char * src, bool popped, yp_compile_context_t *compile_context) { +yp_compile_node(rb_iseq_t *iseq, const yp_node_t *node, LINK_ANCHOR *const ret, const char * src, bool popped, yp_compile_context_t *compile_context) +{ yp_parser_t *parser = compile_context->parser; yp_newline_list_t newline_list = parser->newline_list; int lineno = (int)yp_newline_list_line_column(&newline_list, node->location.start).line; @@ -398,7 +458,9 @@ yp_compile_node(rb_iseq_t *iseq, const yp_node_t *node, LINK_ANCHOR *const ret, case YP_NODE_ASSOC_NODE: { yp_assoc_node_t *assoc_node = (yp_assoc_node_t *) node; yp_compile_node(iseq, assoc_node->key, ret, src, popped, compile_context); - yp_compile_node(iseq, assoc_node->value, ret, src, popped, compile_context); + if (assoc_node->value) { + yp_compile_node(iseq, assoc_node->value, ret, src, popped, compile_context); + } return; } case YP_NODE_ASSOC_SPLAT_NODE: { @@ -703,7 +765,13 @@ yp_compile_node(rb_iseq_t *iseq, const yp_node_t *node, LINK_ANCHOR *const ret, return; } case YP_NODE_IF_NODE: { - yp_compile_if(iseq, node, ret, src, popped, compile_context); + const int line = (int)yp_newline_list_line_column(&(parser->newline_list), node->location.start).line; + yp_if_node_t *if_node = (yp_if_node_t *)node; + yp_statements_node_t *node_body = if_node->statements; + yp_node_t *node_else = if_node->consequent; + yp_node_t *predicate = if_node->predicate; + + yp_compile_if(iseq, line, node_body, node_else, predicate, ret, src, popped, compile_context); return; } case YP_NODE_IMAGINARY_NODE: { @@ -1118,7 +1186,9 @@ yp_compile_node(rb_iseq_t *iseq, const yp_node_t *node, LINK_ANCHOR *const ret, ADD_INSN (ret, &dummy_line_node, nop); ADD_LABEL(ret, start); - yp_compile_node(iseq, (yp_node_t *)(scope_node->body), ret, src, popped, &scope_compile_context); + if (scope_node->body) { + yp_compile_node(iseq, (yp_node_t *)(scope_node->body), ret, src, popped, &scope_compile_context); + } ADD_LABEL(ret, end); ADD_TRACE(ret, RUBY_EVENT_B_RETURN); @@ -1234,77 +1304,31 @@ yp_compile_node(rb_iseq_t *iseq, const yp_node_t *node, LINK_ANCHOR *const ret, return; } case YP_NODE_UNLESS_NODE: { - yp_compile_if(iseq, node, ret, src, popped, compile_context); + const int line = (int)yp_newline_list_line_column(&(parser->newline_list), node->location.start).line; + yp_unless_node_t *unless_node = (yp_unless_node_t *)node; + yp_statements_node_t *node_body = unless_node->statements; + yp_node_t *node_else = (yp_node_t *)(unless_node->consequent); + yp_node_t *predicate = unless_node->predicate; + + yp_compile_if(iseq, line, node_body, node_else, predicate, ret, src, popped, compile_context); + return; + } + case YP_NODE_UNTIL_NODE: { + yp_until_node_t *until_node = (yp_until_node_t *)node; + yp_statements_node_t *statements = until_node->statements; + yp_node_t *predicate = until_node->predicate; + yp_node_flags_t flags = node->flags; + + yp_compile_while(iseq, lineno, flags, node->type, statements, predicate, ret, src, popped, compile_context); return; } case YP_NODE_WHILE_NODE: { yp_while_node_t *while_node = (yp_while_node_t *)node; + yp_statements_node_t *statements = while_node->statements; + yp_node_t *predicate = while_node->predicate; + yp_node_flags_t flags = node->flags; - LABEL *prev_start_label = ISEQ_COMPILE_DATA(iseq)->start_label; - LABEL *prev_end_label = ISEQ_COMPILE_DATA(iseq)->end_label; - LABEL *prev_redo_label = ISEQ_COMPILE_DATA(iseq)->redo_label; - int prev_loopval_popped = ISEQ_COMPILE_DATA(iseq)->loopval_popped; - - // TODO: Deal with ensures in here - LABEL *next_label = ISEQ_COMPILE_DATA(iseq)->start_label = NEW_LABEL(lineno); /* next */ - LABEL *redo_label = ISEQ_COMPILE_DATA(iseq)->redo_label = NEW_LABEL(lineno); /* redo */ - LABEL *break_label = ISEQ_COMPILE_DATA(iseq)->end_label = NEW_LABEL(lineno); /* break */ - LABEL *end_label = NEW_LABEL(lineno); - LABEL *adjust_label = NEW_LABEL(lineno); - - LABEL *next_catch_label = NEW_LABEL(lineno); - LABEL *tmp_label = NULL; - - ISEQ_COMPILE_DATA(iseq)->loopval_popped = 0; - - // begin; end while true - if (while_node->base.flags & YP_LOOP_FLAGS_BEGIN_MODIFIER) { - ADD_INSNL(ret, &dummy_line_node, jump, next_label); - } - else { - // while true; end - tmp_label = NEW_LABEL(lineno); - ADD_INSNL(ret, &dummy_line_node, jump, tmp_label); - } - - ADD_LABEL(ret, adjust_label); - ADD_INSN(ret, &dummy_line_node, putnil); - ADD_LABEL(ret, next_catch_label); - ADD_INSN(ret, &dummy_line_node, pop); - ADD_INSNL(ret, &dummy_line_node, jump, next_label); - if (tmp_label) ADD_LABEL(ret, tmp_label); - - ADD_LABEL(ret, redo_label); - if (while_node->statements) { - yp_compile_node(iseq, (yp_node_t *)while_node->statements, ret, src, Qfalse, compile_context); - } - - ADD_LABEL(ret, next_label); - - yp_compile_branch_condition(iseq, ret, while_node->predicate, redo_label, end_label, src, popped, compile_context); - - ADD_LABEL(ret, end_label); - ADD_ADJUST_RESTORE(ret, adjust_label); - - ADD_INSN(ret, &dummy_line_node, putnil); - - ADD_LABEL(ret, break_label); - - if (popped) { - ADD_INSN(ret, &dummy_line_node, pop); - } - - ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, redo_label, break_label, NULL, - break_label); - ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, redo_label, break_label, NULL, - next_catch_label); - ADD_CATCH_ENTRY(CATCH_TYPE_REDO, redo_label, break_label, NULL, - ISEQ_COMPILE_DATA(iseq)->redo_label); - - ISEQ_COMPILE_DATA(iseq)->start_label = prev_start_label; - ISEQ_COMPILE_DATA(iseq)->end_label = prev_end_label; - ISEQ_COMPILE_DATA(iseq)->redo_label = prev_redo_label; - ISEQ_COMPILE_DATA(iseq)->loopval_popped = prev_loopval_popped; + yp_compile_while(iseq, lineno, flags, node->type, statements, predicate, ret, src, popped, compile_context); return; } case YP_NODE_X_STRING_NODE: { |