diff options
Diffstat (limited to 'ext/B/ramblings/flip-flop')
-rw-r--r-- | ext/B/ramblings/flip-flop | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/ext/B/ramblings/flip-flop b/ext/B/ramblings/flip-flop new file mode 100644 index 0000000000..183d541b98 --- /dev/null +++ b/ext/B/ramblings/flip-flop @@ -0,0 +1,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: +... |