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