summaryrefslogtreecommitdiffstats
path: root/contrib/perl5/ext/B/ramblings/flip-flop
blob: 183d541b98271bc8bd2d45dd444f139aaf24830a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
PP(pp_range)
{
    if (GIMME == G_ARRAY)
        return cCONDOP->op_true;
    return SvTRUEx(PAD_SV(op->op_targ)) ? cCONDOP->op_false : cCONDOP->op_true;
}

pp_range is a CONDOP.
In array context, it just returns op_true.
In scalar context it checks the truth of targ and returns
op_false if true, op_true if false.

flip is an UNOP.
It "looks after" its child which is always a pp_range CONDOP.
In array context, it just returns the child's op_false.
In scalar context, there are three possible outcomes:
  (1) set child's targ to 1, our targ to 1 and return op_next.
  (2) set child's targ to 1, our targ to 0, sp-- and return child's op_false.
  (3) Blank targ and  TOPs and return op_next.
Case 1 happens for a "..." with a matching lineno... or true TOPs.
Case 2 happens for a ".." with a matching lineno... or true TOPs.
Case 3 happens for a non-matching lineno or false TOPs.

               $a = lhs..rhs;

        ,------->  range
        ^         /     \
        |    true/       \false
        |       /         \
   first|     lhs        rhs
        |      \   first   /
        ^--- flip <----- flop
                 \       /
                  \     /
                  sassign


/* range */
if (SvTRUE(curpad[op->op_targ]))
    goto label(op_false);
/* op_true */
...
/* flip */
/* For "..." returns op_next. For ".." returns op_next or op_first->op_false */
/* end of basic block */
goto out;
label(range op_false):
...
/* flop */
out:
...
OpenPOWER on IntegriCloud