Skip to content

Commit

Permalink
[Bug #19877] Flip-flop needs to be direct condition
Browse files Browse the repository at this point in the history
  • Loading branch information
nobu committed Dec 8, 2023
1 parent 8bb90f4 commit 9b7a964
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 19 deletions.
23 changes: 12 additions & 11 deletions parse.y
Expand Up @@ -14108,7 +14108,7 @@ enum cond_type {
} \
} while (0)

static NODE *cond0(struct parser_params*,NODE*,enum cond_type,const YYLTYPE*);
static NODE *cond0(struct parser_params*,NODE*,enum cond_type,const YYLTYPE*,bool);

static NODE*
range_op(struct parser_params *p, NODE *node, const YYLTYPE *loc)
Expand All @@ -14124,19 +14124,19 @@ range_op(struct parser_params *p, NODE *node, const YYLTYPE *loc)
ID lineno = rb_intern("$.");
return NEW_CALL(node, tEQ, NEW_LIST(NEW_GVAR(lineno, loc), loc), loc);
}
return cond0(p, node, COND_IN_FF, loc);
return cond0(p, node, COND_IN_FF, loc, true);
}

static NODE*
cond0(struct parser_params *p, NODE *node, enum cond_type type, const YYLTYPE *loc)
cond0(struct parser_params *p, NODE *node, enum cond_type type, const YYLTYPE *loc, bool top)
{
if (node == 0) return 0;
if (!(node = nd_once_body(node))) return 0;
assign_in_cond(p, node);

switch (nd_type(node)) {
case NODE_BEGIN:
RNODE_BEGIN(node)->nd_body = cond0(p, RNODE_BEGIN(node)->nd_body, type, loc);
RNODE_BEGIN(node)->nd_body = cond0(p, RNODE_BEGIN(node)->nd_body, type, loc, top);
break;

case NODE_DSTR:
Expand All @@ -14151,17 +14151,18 @@ cond0(struct parser_params *p, NODE *node, enum cond_type type, const YYLTYPE *l
return NEW_MATCH2(node, NEW_GVAR(idLASTLINE, loc), loc);

case NODE_BLOCK:
RNODE_BLOCK(RNODE_BLOCK(node)->nd_end)->nd_head = cond0(p, RNODE_BLOCK(RNODE_BLOCK(node)->nd_end)->nd_head, type, loc);
RNODE_BLOCK(RNODE_BLOCK(node)->nd_end)->nd_head = cond0(p, RNODE_BLOCK(RNODE_BLOCK(node)->nd_end)->nd_head, type, loc, false);
break;

case NODE_AND:
case NODE_OR:
RNODE_AND(node)->nd_1st = cond0(p, RNODE_AND(node)->nd_1st, COND_IN_COND, loc);
RNODE_AND(node)->nd_2nd = cond0(p, RNODE_AND(node)->nd_2nd, COND_IN_COND, loc);
RNODE_AND(node)->nd_1st = cond0(p, RNODE_AND(node)->nd_1st, COND_IN_COND, loc, true);
RNODE_AND(node)->nd_2nd = cond0(p, RNODE_AND(node)->nd_2nd, COND_IN_COND, loc, true);
break;

case NODE_DOT2:
case NODE_DOT3:
if (!top) break;
RNODE_DOT2(node)->nd_beg = range_op(p, RNODE_DOT2(node)->nd_beg, loc);
RNODE_DOT2(node)->nd_end = range_op(p, RNODE_DOT2(node)->nd_end, loc);
if (nd_type_p(node, NODE_DOT2)) nd_set_type(node,NODE_FLIP2);
Expand Down Expand Up @@ -14198,14 +14199,14 @@ static NODE*
cond(struct parser_params *p, NODE *node, const YYLTYPE *loc)
{
if (node == 0) return 0;
return cond0(p, node, COND_IN_COND, loc);
return cond0(p, node, COND_IN_COND, loc, true);
}

static NODE*
method_cond(struct parser_params *p, NODE *node, const YYLTYPE *loc)
{
if (node == 0) return 0;
return cond0(p, node, COND_IN_OP, loc);
return cond0(p, node, COND_IN_OP, loc, true);
}

static NODE*
Expand All @@ -14219,15 +14220,15 @@ static NODE*
new_if(struct parser_params *p, NODE *cc, NODE *left, NODE *right, const YYLTYPE *loc)
{
if (!cc) return right;
cc = cond0(p, cc, COND_IN_COND, loc);
cc = cond0(p, cc, COND_IN_COND, loc, true);
return newline_node(NEW_IF(cc, left, right, loc));
}

static NODE*
new_unless(struct parser_params *p, NODE *cc, NODE *left, NODE *right, const YYLTYPE *loc)
{
if (!cc) return right;
cc = cond0(p, cc, COND_IN_COND, loc);
cc = cond0(p, cc, COND_IN_COND, loc, true);
return newline_node(NEW_UNLESS(cc, left, right, loc));
}

Expand Down
20 changes: 12 additions & 8 deletions test/ruby/test_parse.rb
Expand Up @@ -466,21 +466,25 @@ def test_define_singleton_error
end

def test_flip_flop
[
'((cond1..cond2))',
'(; cond1..cond2)',
all_assertions_foreach(nil,
['(cond1..cond2)', true],
['((cond1..cond2))', true],

# '(;;;cond1..cond2)', # don't care

'(1; cond1..cond2)',
'(%s(); cond1..cond2)',
'(%w(); cond1..cond2)',
'(1; (2; (3; 4; cond1..cond2)))',
'(1+1; cond1..cond2)',
].each do |code|
) do |code, pass|
code = code.sub("cond1", "n==4").sub("cond2", "n==5")
begin
$VERBOSE, verbose_bak = nil, $VERBOSE
if pass
assert_equal([4,5], eval("(1..9).select {|n| true if #{code}}"))
ensure
$VERBOSE = verbose_bak
else
assert_raise_with_message(ArgumentError, /bad value for range/, code) {
eval("[4].each {|n| true if #{code}}")
}
end
end
end
Expand Down

0 comments on commit 9b7a964

Please sign in to comment.