in reply to Re^8: Unhappy returns
in thread Unhappy returns
Note also that while Perl makes a difference between functions and statements (mostly for the benefit of mortals), perl doesn't. Operators, functions, statements, they're all opcodes. Here's the handling of the leaveloop opcode:#!/usr/bin/perl use strict; use warnings; my $x = do {for (1 .. 4) {}}; my @x = do {for (1 .. 4) {}}; printf "Scalar return value of for is %s\n", defined $x ? "defined" : "undefined"; printf "Scalar return value of for is %s\n", $x ? "true" : "false"; printf "Scalar return value of for is has length %d\n", length $x; printf "Scalar return value of for is '%s'\n", $x; printf "List return value of for returns %d element\n", scalar @x; printf "List return value of for contains %d undefined elements\n", scalar grep {!defined} @x; printf "List return value of for contains %d true elements\n", scalar grep {$_} @x; printf "List return value of for contains %d elements of non-zero leng +th\n", scalar grep {length} @x; printf "List return value of for equals [%s]\n", join ", ", map {"'$_'"} @x; __END__ Scalar return value of for is defined Scalar return value of for is false Scalar return value of for is has length 0 Scalar return value of for is '' List return value of for returns 1 element List return value of for contains 0 undefined elements List return value of for contains 0 true elements List return value of for contains 0 elements of non-zero length List return value of for equals ['']
You don't have to understand what it does, but do note that it's looking at its context to determine what to leave behind on the stack.PP(pp_leaveloop) { dSP; register PERL_CONTEXT *cx; I32 gimme; SV **newsp; PMOP *newpm; SV **mark; POPBLOCK(cx,newpm); mark = newsp; newsp = PL_stack_base + cx->blk_loop.resetsp; TAINT_NOT; if (gimme == G_VOID) ; /* do nothing */ else if (gimme == G_SCALAR) { if (mark < SP) *++newsp = sv_mortalcopy(*SP); else *++newsp = &PL_sv_undef; } else { while (mark < SP) { *++newsp = sv_mortalcopy(*++mark); TAINT_NOT; /* Each item is independent */ } } SP = newsp; PUTBACK; POPLOOP(cx); /* Stack values are safe: release loop vars .. +. */ PL_curpm = newpm; /* ... and pop $1 et al */ LEAVE; LEAVE; return NORMAL; }
And here is a trace:
perl -Dt -e '$x = do {for (1) {}}' EXECUTING... (-e:0) enter (-e:0) nextstate (-e:1) pushmark (-e:1) const(IV(1)) (-e:1) gv(main::_) (-e:1) enteriter (-e:1) iter (-e:1) and (-e:1) stub (-e:1) unstack (-e:1) iter (-e:1) and (-e:1) leaveloop (-e:1) gvsv(main::x) (-e:1) sassign (-e:1) leave
|
|---|