зеркало из https://github.com/github/ruby.git
[Prism] Fix IfNode and ElseNode
ElseNode looks to have been implemented at the same time as IfNode, but was resulting in a stack underflow error. The following is from the test code ``` if foo bar end ``` ``` ❯ make run compiling compile.c linking miniruby ./miniruby -I./lib -I. -I.ext/common -r./arm64-darwin22-fake ./test.rb CRUBY: ************************************************** == disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(2,19)> 0000 putself ( 2)[Li] 0001 opt_send_without_block <calldata!mid:foo, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0003 branchunless 9 0005 putself 0006 opt_send_without_block <calldata!mid:bar, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0008 pop 0009 putobject_INT2FIX_1_ 0010 leave PRISM: ************************************************** -- raw disasm-------- 0000 putself ( 2) 0001 send <calldata:foo, 0>, nil ( 2) 0004 branchunless <L001> ( 2) 0006 jump <L000> ( 2) <L000> [sp: 0] * 0008 pop ( 1) 0009 putself ( 2) 0010 send <calldata:bar, 0>, nil ( 2) 0013 pop ( 2) 0014 jump <L002> ( 1) <L001> [sp: 0] <L002> [sp: -1] 0016 putobject 1 ( 2) 0018 leave ( 1) --------------------- <compiled>: <compiled>:1: argument stack underflow (-1) (SyntaxError) make: *** [run] Error 1 ``` This commit fixes the stack underflow error for both IfNode and ElseNode and introduces tests for them.
This commit is contained in:
Родитель
f834b1a40d
Коммит
05b9b58d55
|
@ -407,7 +407,6 @@ pm_compile_if(rb_iseq_t *iseq, const int line, pm_statements_node_t *node_body,
|
|||
INIT_ANCHOR(then_seq);
|
||||
if (node_body) {
|
||||
pm_compile_node(iseq, (pm_node_t *)node_body, then_seq, src, popped, compile_context);
|
||||
PM_POP_IF_POPPED;
|
||||
} else {
|
||||
PM_PUTNIL_UNLESS_POPPED;
|
||||
}
|
||||
|
@ -415,7 +414,6 @@ pm_compile_if(rb_iseq_t *iseq, const int line, pm_statements_node_t *node_body,
|
|||
if (else_label->refcnt) {
|
||||
end_label = NEW_LABEL(line);
|
||||
ADD_INSNL(then_seq, &dummy_line_node, jump, end_label);
|
||||
PM_POP_UNLESS_POPPED;
|
||||
}
|
||||
ADD_SEQ(ret, then_seq);
|
||||
}
|
||||
|
@ -426,7 +424,7 @@ pm_compile_if(rb_iseq_t *iseq, const int line, pm_statements_node_t *node_body,
|
|||
DECL_ANCHOR(else_seq);
|
||||
INIT_ANCHOR(else_seq);
|
||||
if (node_else) {
|
||||
pm_compile_node(iseq, (pm_node_t *)(((pm_else_node_t *)node_else)->statements), else_seq, src, popped, compile_context);
|
||||
pm_compile_node(iseq, (pm_node_t *)node_else, else_seq, src, popped, compile_context);
|
||||
}
|
||||
else {
|
||||
PM_PUTNIL_UNLESS_POPPED;
|
||||
|
@ -1365,6 +1363,11 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
|
|||
ADD_INSN1(ret, &dummy_line_node, putobject, Qfalse);
|
||||
}
|
||||
return;
|
||||
case PM_ELSE_NODE: {
|
||||
pm_else_node_t *cast = (pm_else_node_t *)node;
|
||||
PM_COMPILE((pm_node_t *)cast->statements);
|
||||
return;
|
||||
}
|
||||
case PM_FLIP_FLOP_NODE: {
|
||||
// TODO: The labels here are wrong, figure out why.....
|
||||
pm_flip_flop_node_t *flip_flop_node = (pm_flip_flop_node_t *)node;
|
||||
|
|
|
@ -338,6 +338,18 @@ module Prism
|
|||
test_prism_eval("false || 1")
|
||||
end
|
||||
|
||||
def test_IfNode
|
||||
test_prism_eval("if true; 1; end")
|
||||
test_prism_eval("1 if true")
|
||||
end
|
||||
|
||||
def test_ElseNode
|
||||
test_prism_eval("if false; 0; else; 1; end")
|
||||
test_prism_eval("if true; 0; else; 1; end")
|
||||
test_prism_eval("true ? 1 : 0")
|
||||
test_prism_eval("false ? 0 : 1")
|
||||
end
|
||||
|
||||
############################################################################
|
||||
# Calls / arugments #
|
||||
############################################################################
|
||||
|
|
Загрузка…
Ссылка в новой задаче