This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Integrate from maint:
[perl5.git] / ext / B / ramblings / flip-flop
1 PP(pp_range)
2 {
3     if (GIMME == G_ARRAY)
4         return NORMAL;
5     if (SvTRUEx(PAD_SV(PL_op->op_targ)))
6         return cLOGOP->op_other;
7     else
8         return NORMAL;
9 }
10
11 pp_range is a LOGOP.
12 In list context, it just returns op_next.
13 In scalar context it checks the truth of targ and returns
14 op_other if true, op_next if false.
15
16 flip is an UNOP.
17 It "looks after" its child which is always a pp_range LOGOP.
18 In list context, it just returns the child's op_other.
19 In scalar context, there are three possible outcomes:
20   (1) set child's targ to 1, our targ to 1 and return op_next.
21   (2) set child's targ to 1, our targ to 0, sp-- and return child's op_other.
22   (3) Blank targ and  TOPs and return op_next.
23 Case 1 happens for a "..." with a matching lineno... or true TOPs.
24 Case 2 happens for a ".." with a matching lineno... or true TOPs.
25 Case 3 happens for a non-matching lineno or false TOPs.
26
27                $a = lhs..rhs;
28
29         ,------->  range
30         ^         /     \
31         |    true/       \false
32         |       /         \
33    first|     lhs        rhs
34         |      \   first   /
35         ^--- flip <----- flop
36                  \       /
37                   \     /
38                   sassign
39
40
41 /* range */
42 if (SvTRUE(curpad[op->op_targ]))
43     goto label(op_other);
44 /* op_next */
45 ...
46 /* flip */
47 /* For "..." returns op_next. For ".." returns op_next or op_first->op_other */
48 /* end of basic block */
49 goto out;
50 label(range op_other):
51 ...
52 /* flop */
53 out:
54 ...