diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-03-11 22:37:50 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-03-11 22:37:50 +0000 |
commit | 8c3108abca2209e79b103d4cababb837c45baef9 (patch) | |
tree | 35778d49e96f5055a6a65521e082936a607628a7 /compile.c | |
parent | 4b1cc574a061e45df6c38cb6d173a5dfd037063d (diff) | |
download | ruby-8c3108abca2209e79b103d4cababb837c45baef9.tar.gz |
compile.c: compile_when
* compile.c (compile_when): extract from iseq_compile_each.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57889 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'compile.c')
-rw-r--r-- | compile.c | 106 |
1 files changed, 56 insertions, 50 deletions
@@ -4102,6 +4102,60 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped) return COMPILE_OK; } +static int +compile_when(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popped) +{ + NODE *vals; + NODE *val; + NODE *orig_node = node; + LABEL *endlabel; + DECL_ANCHOR(body_seq); + + INIT_ANCHOR(body_seq); + endlabel = NEW_LABEL(nd_line(node)); + + while (node && nd_type(node) == NODE_WHEN) { + const int line = nd_line(node); + LABEL *l1 = NEW_LABEL(line); + ADD_LABEL(body_seq, l1); + CHECK(COMPILE_(body_seq, "when", node->nd_body, popped)); + ADD_INSNL(body_seq, line, jump, endlabel); + + vals = node->nd_head; + if (!vals) { + compile_bug(ERROR_ARGS "NODE_WHEN: must be NODE_ARRAY, but 0"); + } + switch (nd_type(vals)) { + case NODE_ARRAY: + while (vals) { + val = vals->nd_head; + CHECK(COMPILE(ret, "when2", val)); + ADD_INSNL(ret, nd_line(val), branchif, l1); + vals = vals->nd_next; + } + break; + case NODE_SPLAT: + case NODE_ARGSCAT: + case NODE_ARGSPUSH: + ADD_INSN(ret, nd_line(vals), putnil); + CHECK(COMPILE(ret, "when2/cond splat", vals)); + ADD_INSN1(ret, nd_line(vals), checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_WHEN | VM_CHECKMATCH_ARRAY)); + ADD_INSNL(ret, nd_line(vals), branchif, l1); + break; + default: + UNKNOWN_NODE("NODE_WHEN", vals); + } + node = node->nd_next; + } + /* else */ + CHECK(COMPILE_(ret, "else", node, popped)); + ADD_INSNL(ret, nd_line(orig_node), jump, endlabel); + + ADD_SEQ(ret, body_seq); + ADD_LABEL(ret, endlabel); + return COMPILE_OK; +} + /** compile each node @@ -4189,57 +4243,9 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int poppe case NODE_CASE: CHECK(compile_case(iseq, ret, node, popped)); break; - case NODE_WHEN:{ - NODE *vals; - NODE *val; - NODE *orig_node = node; - LABEL *endlabel; - DECL_ANCHOR(body_seq); - - INIT_ANCHOR(body_seq); - endlabel = NEW_LABEL(line); - - while (node && nd_type(node) == NODE_WHEN) { - LABEL *l1 = NEW_LABEL(line = nd_line(node)); - ADD_LABEL(body_seq, l1); - CHECK(COMPILE_(body_seq, "when", node->nd_body, popped)); - ADD_INSNL(body_seq, line, jump, endlabel); - - vals = node->nd_head; - if (!vals) { - compile_bug(ERROR_ARGS "NODE_WHEN: must be NODE_ARRAY, but 0"); - } - switch (nd_type(vals)) { - case NODE_ARRAY: - while (vals) { - val = vals->nd_head; - CHECK(COMPILE(ret, "when2", val)); - ADD_INSNL(ret, nd_line(val), branchif, l1); - vals = vals->nd_next; - } - break; - case NODE_SPLAT: - case NODE_ARGSCAT: - case NODE_ARGSPUSH: - ADD_INSN(ret, nd_line(vals), putnil); - CHECK(COMPILE(ret, "when2/cond splat", vals)); - ADD_INSN1(ret, nd_line(vals), checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_WHEN | VM_CHECKMATCH_ARRAY)); - ADD_INSNL(ret, nd_line(vals), branchif, l1); - break; - default: - UNKNOWN_NODE("NODE_WHEN", vals); - } - node = node->nd_next; - } - /* else */ - CHECK(COMPILE_(ret, "else", node, popped)); - ADD_INSNL(ret, nd_line(orig_node), jump, endlabel); - - ADD_SEQ(ret, body_seq); - ADD_LABEL(ret, endlabel); - + case NODE_WHEN: + CHECK(compile_when(iseq, ret, node, popped)); break; - } case NODE_OPT_N: case NODE_WHILE: case NODE_UNTIL:{ |