File Coverage

blib/lib/Perl6/Contexts.pm
Criterion Covered Total %
statement 178 200 89.0
branch 59 80 73.7
condition 28 50 56.0
subroutine 15 16 93.7
pod 0 3 0.0
total 280 349 80.2


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             # Here, localtime() should return a stringified date or an object
4             # use Perl6::Contexts;
5             # my @stuff = (1, 2, 3, localtime);
6             # print "@stuff\n";
7             # 1 2 3 27 12 10 8 8 104 3 251 0
8              
9             # TODO - make this work:
10             # use Perl6::Contexts;
11             # my %hash = { foo => 10, bar => 20 };
12             # foreach my $key (keys %hash) {
13             # print $key, "\n";
14             # }
15             # HASH(0x813808c)
16              
17             # TODO - make this work:
18             # perl -MO=Concise -e 'my @foo; my $bar = [ 1 .. 20 ]; @foo = $bar;'
19             # c <;> nextstate(main 3 -e:1) v ->d
20             # h <2> aassign[t5] vKS ->i
21             # - <1> ex-list lK ->f
22             # d <0> pushmark s ->e
23             # e <0> padsv[$bar:2,3] l ->f
24             # - <1> ex-list lK ->h
25             # f <0> pushmark s ->g
26             # g <0> padav[@foo:1,3] lRM* ->h
27              
28             # Reference found where even-sized list expected = my %foo = { }
29              
30             # TODO - make this work:
31             # perl -MO=Concise -e 'localtime->date();'
32             # 7 <@> leave[1 ref] vKP/REFC ->(end)
33             # 1 <0> enter ->2
34             # 2 <;> nextstate(main 1 -e:1) v ->3
35             # 6 <1> entersub[t2] vKS/TARG ->7
36             # 3 <0> pushmark s ->4
37             # 4 <0> localtime[t1] sM ->5
38             # 5 <$> method_named(PVIV "date") ->6
39             # this will require numerous helper classes, one for stat buffers, time,
40             # and any other built-in that returns a list in list context. perhaps can
41             # reuse existing classes like Date::Manip.
42              
43              
44             package Perl6::Contexts;
45              
46             # use Data::Dumper 'Dumper'; # debug
47              
48 1     1   29811 use 5.008;
  1         3  
  1         66  
49             our $VERSION = '0.4';
50              
51             #
52             # some preliminary goop is gotten out of the way first, and then we get into the meat which
53             # starts with the CHECK() routine. that calls one_cv_at_a_time() for each code value,
54             # which calls walkoptree_slow() after some prep work, which calls look_for_things_to_diddle()
55             # for each actual bytecode instruction.
56             #
57              
58 1     1   6 use B 'OPf_KIDS', 'OPf_WANT_SCALAR', 'OPf_WANT_LIST', 'OPf_WANT', 'OPf_REF', 'OPf_MOD', 'OPf_SPECIAL';
  1         2  
  1         106  
59 1     1   943 use B::Generate;
  1         2828  
  1         51  
60 1     1   1767 use B::Concise 'concise_cv'; # 'walk_topdown'
  1         15548  
  1         364  
61             # use B::Utils;
62              
63 1     1   8 use strict;
  1         2  
  1         32  
64 1     1   5 use warnings;
  1         2  
  1         384  
65              
66             sub OPfDEREF () { 32|64 } # #define OPpDEREF (32|64) /* autovivify: Want ref to something: */
67             sub OPfDEREF_AV () { 32 } # #define OPpDEREF_AV 32 /* Want ref to AV. */
68             sub OPfDEREF_HV () { 64 } # #define OPpDEREF_HV 64 /* Want ref to HV. */
69             sub OPfDEREF_SV () { 32|64 } # #define OPpDEREF_SV (32|64) /* Want ref to SV. */
70              
71             my $redo_reverse_indices; # recompute $previous for the current CV
72             my $previous = {}; # opposite of next, inferred from next
73             my %knownuniverse; # modules using us
74             my %knowncvs; # code values we've found (subroutines and anonymous subs)
75             my @padtmps; # pad entry offsets available for our consumption
76             my $lastpadtmp; # last one used - go round robin
77             my %did_already; # arrays were getting ref'd twice because parent info was stale and two rules matched
78              
79             my $lastpack; my $lastline; my $lastfile;
80              
81             # numericish opcodes, taken from perldoc Opcodes
82             # stringwise: slt sgt sle sge seq sne scmp
83              
84             my $mathops = { map { ($_ => 1) } qw{
85             preinc i_preinc predec i_predec postinc i_postinc postdec i_postdec
86             int hex oct abs pow multiply i_multiply divide i_divide
87             modulo i_modulo add i_add subtract i_subtract
88              
89             left_shift right_shift bit_and bit_xor bit_or negate i_negate
90             not complement
91              
92             lt i_lt gt i_gt le i_le ge i_ge eq i_eq ne i_ne ncmp i_ncmp
93              
94             atan2 sin cos exp log sqrt
95             rand srand
96              
97             scalar
98             }};
99              
100             my $boolops = { map { ($_ => 1) } qw{
101             cond_expr flip flop andassign orassign dorassign and or dor xor
102             }};
103              
104             my $stringops = { map { ($_ => 1) } qw{
105             slt sgt sle sge seq sne scmp
106              
107             substr vec stringify study pos length index rindex ord chr
108              
109             ucfirst lcfirst uc lc quotemeta trans chop schop chomp schomp
110              
111             match split qr
112             concat
113             }};
114              
115             my $arrayops = { map { ($_ => 1) } qw{
116             splice push pop shift unshift reverse
117             }};
118              
119             my $hashops = { map { ($_ => 1) } qw{
120             each values keys exists delete
121             }};
122              
123             sub import {
124 1     1   12 my $caller = caller;
125 1         32 $knownuniverse{$caller} = 1;
126             }
127              
128             CHECK {
129              
130             # make a hash of code values we've found - memory address of the opcode is mapped to the
131             # B object encapsulating it. then go through them all, marking them done as we do them.
132             # this is tricky since more may appear as we go along. for each code value we find, call
133             # one_cv_at_a_time() on it.
134              
135             # build initial list of code values from methods/functions in the subs and the main root
136              
137 1     1   2312 %knowncvs = do { my $x = B::main_cv(); ( $$x => $x ) };
  1         6  
  1         18  
138              
139 1         7 foreach my $package (keys %knownuniverse) {
140 1     1   6 no strict 'refs';
  1         4  
  1         3467  
141 1         2 foreach my $method (grep { defined &{$package.'::'.$_} } keys %{$package.'::'}) {
  200         191  
  200         589  
  1         390  
142 3         4 my $cv = B::svref_2object(*{$package.'::'.$method}{CODE});
  3         15  
143 3         22 $knowncvs{$$cv} = $cv;
144             }
145             }
146              
147 1         33 foreach my $cv ((B::main_cv->PADLIST->ARRAY)[1]->ARRAY) {
148             # print "debug: main pad list: ", ref $cv, "\n";
149 44 50       86 next unless ref $cv eq 'B::CV';
150             # print "debug: found a cv!\n";
151 0         0 $knowncvs{$$cv} = $cv;
152             }
153              
154              
155 1         58 my %donecvs;
156             my $curcv;
157              
158 1         5 goto first_cv;
159              
160 4         12 next_cv:
161              
162             one_cv_at_a_time($curcv);
163 4         15 $donecvs{$curcv} = 1;
164              
165             first_cv:
166              
167 5         20 foreach (keys %knowncvs) {
168             # we look through the list of code values each time just in case something got added
169             # this happens when we encounter anoncode operations
170 14 100       23 $curcv = $knowncvs{$_}; goto next_cv if ! $donecvs{$curcv};
  14         1331  
171             }
172              
173             }
174              
175             sub one_cv_at_a_time {
176              
177             # get ready to recurse through the bytecode tree - build a reverse index, previous, from the next
178             # links and do any debugging output after we traverse the tree
179              
180 4     4 0 5 my $curcv = shift;
181 4         26 my $leave = $curcv->ROOT;
182              
183 4 50       39 return if $curcv->PADLIST->isa('B::SPECIAL');
184 4         45 my @nonrootpad = ($curcv->PADLIST->ARRAY)[0]->ARRAY;
185              
186             # XXX - locate some temporaries we can use.
187             # this routine *should* build a list of all temporaries for the CV and then remove the list of
188             # temporaries already used in the current statement but for now we're just going to use some
189             # ringers. ringers also deal with the problem of modifiying the most complex statement
190             # in a CV where all temps are in use a d we can't make more!
191              
192 4         17 for(my $padindex = 0; $padindex < @nonrootpad; $padindex++) {
193 24         34 my $name = $nonrootpad[$padindex];
194             # that's the inidivual entries of the names array - see the comments in pad.c in the perl source
195 24 100       76 next if ref $name eq 'B::SPECIAL'; # B::SPECIALs are PADTMPs which are exactly what we *should* be using
196             # print 'PVX: ', $name->PVX, ' NV: ', $name->NV, ' IV: ', $name->IV, "\n";
197 7 100       52 next unless $name->PVX =~ m/^\$t[0-9]$/; # XXX might have to fix up flags a bit here
198             # my $sv = (($curcv->PADLIST->ARRAY)[1]->ARRAY)[0]; bless $sv, 'B::PV'; $sv->PV('');
199 3         12 push @padtmps, $padindex;
200             # print "debug: $padindex is a temp for us - ", $name->PVX, "\n";
201             }
202              
203             $redo_reverse_indices = sub {
204             walkoptree_slow($leave, sub {
205 3556 100 66     3964 my $self = shift; return unless $self and $$self;
  3556         15033  
206 2497 100 66     7791 my $next = $self->next; return unless $next and $$next;
  2497         10208  
207 2485         7686 $previous->{$$next} = $self;
208 12     12   59 });
209 4         17 };
210              
211 4         16 $redo_reverse_indices->();
212              
213 4         24 walkoptree_slow($leave, \&look_for_things_to_diddle);
214              
215             # B::main_root()->linklist();
216              
217             # print $$leave, " basic:\n"; B::Concise::concise_cv_obj('basic', $curcv); # debug
218             # print $$leave, " exec:\n"; B::Concise::concise_cv_obj('exec', $curcv); # debug
219              
220 4         19 return 1;
221             }
222              
223             my @parents = ();
224              
225             sub walkoptree_slow {
226             # actually recurse the bytecode tree
227             # stolen from B.pm, modified
228 3993     3993 0 4902 my $op = shift;
229 3993         4572 my $sub = shift;
230 3993         4722 my $level = shift;
231 3993   100     7477 $level ||= 0;
232             # warn(sprintf("walkoptree: %d. %s\n", $level, peekop($op))) if $debug;
233 3993         7285 $sub->($op, $level, \@parents);
234 3993 100 100     23568 if ($op->can('flags') and $op->flags() & OPf_KIDS) {
235             # print "debug: go: ", ' ' x $level, $op->name(), "\n"; # debug
236 1190         1765 push @parents, $op;
237 1190         3913 my $kid = $op->first();
238 1190         1544 my $next;
239 3977         5149 next_kid:
240             # was being changed right out from under us, so pre-compute
241 3977 100       13407 $next = 0; $next = $kid->sibling() if $$kid;
242 3977         8690 walkoptree_slow($kid, $sub, $level + 1);
243 3977         6912 $kid = $next;
244 3977 100       11261 goto next_kid if $kid;
245 1190         1910 pop @parents;
246             }
247 3993 0 33     32424 if (B::class($op) eq 'PMOP' && $op->pmreplroot() && ${$op->pmreplroot()}) {
  0   33     0  
248             # pattern-match operators
249 0         0 push @parents, $op;
250 0         0 walkoptree_slow($op->pmreplroot(), $sub, $level + 1);
251 0         0 pop @parents;
252             }
253             };
254              
255             sub look_for_things_to_diddle {
256            
257             # $sub->($op, $prev, $parfirst, $parlast, $level);
258              
259 437     437 0 496 my $self = shift; # op object
260 437         532 my $level = shift;
261 437         485 my $parents = shift;
262              
263 437 100 66     1947 return unless $self and $$self;
264              
265 306 100       611 return unless exists $parents->[0]; # root op isn't that interesting and we need a parent
266 302         406 my $parent = $parents->[-1];
267 302         336 my $non_null_parent = do { my $i = -1; $i-- until $parents->[$i]->name() ne 'null'; $parents->[$i]; };
  302         348  
  302         1929  
  302         561  
268              
269 302 100       1290 if($self->name() eq 'nextstate') {
270              
271             # record where we are in the program for any diagnstics
272            
273             # $lastpack = $self->stash()->PV(); # NAME();
274 32         40 $lastpack = '';
275 32         99 $lastfile = $self->file();
276 32         86 $lastline = $self->line();
277              
278             }
279              
280             # return unless $self->name() eq 'padav' or $self->name() eq 'padhv';
281              
282             # print "debug: go: ", $self->name(), "\n";
283              
284             # create some reusable logic to do the actual bytecode splicing
285              
286             my $padav_to_ref = sub {
287              
288             # the bytecode tree is both a tree (built with ->sibling and ->first) and a thread
289             # (threaded with ->next, as well as some special ones for loops and conditionals).
290             # this logic modifies both at the same time so that other B::Generate hacks have a
291             # valid tree to work on and so that the bytecode actually executes.
292             # see http://perldesignpatterns.com/?PerlAssembly
293              
294             # print "debug: doing padav_to_ref $lastpack $lastfile $lastline\n";
295             # print "modifying ", $self->name, " at addresss ", $$self, "\n";
296              
297 7     7   9 my $padav = $self;
298 7 50       30 my $nextstate = $previous->{$$padav} or die "no previous"; # may not actually be a nextstate but that's okey
299 7         23 my $padav_next = $padav->next;
300 7         25 my $padav_sibling = $padav->sibling; # may be 0
301              
302 7         129 my $list = B::LISTOP->new('list', OPf_WANT_LIST | OPf_KIDS | OPf_REF | OPf_MOD, 0, 0);
303 7         53 my $pushmark = B::OP->new('pushmark', OPf_WANT_SCALAR | OPf_REF | OPf_MOD);
304 7         83 my $refgen = B::UNOP->new('refgen', OPf_WANT_SCALAR | OPf_KIDS | OPf_MOD, 0);
305              
306 7         25 $nextstate->next($pushmark);
307 7 100 66     39 $nextstate->sibling($refgen) if $nextstate->can('sibling') and ${$nextstate->sibling} == $$padav;
  7         60  
308              
309 7 100 66     32 $parent->first($refgen) if $parent->can('first') and ${$parent->first} == $$padav;
  7         55  
310 7 50 66     43 $parent->last($refgen) if $parent->can('last') and ${$parent->last} == $$padav;
  3         17  
311              
312 7         24 $list->first($pushmark);
313 7         30 $list->last($padav);
314 7         20 $list->next($pushmark); # $list isn't ever called and in non-fudged bytecode it is optimized away
315              
316 7         21 $pushmark->next($padav);
317 7         20 $pushmark->sibling($padav);
318              
319 7         21 $padav->next($refgen);
320 7         25 $padav->flags(OPf_WANT_LIST | OPf_REF | OPf_MOD);
321 7         22 $padav->sibling(0);
322              
323 7         21 $refgen->first($list);
324 7         20 $refgen->next($padav_next);
325 7         19 $refgen->sibling($padav_sibling);
326              
327 7         20 $did_already{$$self}++;
328 7         18 $redo_reverse_indices->();
329              
330 302         1384 };
331              
332             my $insert_rv2av = sub {
333              
334             # disused because of problems with perl not liking push $foo, $bar in the least ;)
335              
336             # print "debug: doing insert_rv2av $lastpack $lastfile $lastline\n";
337              
338 0     0   0 my $padsv = $self;
339 0         0 my $padsv_next = $padsv->next;
340 0         0 my $padsv_sibling = $padsv->sibling; # may be 0
341 0         0 my $rv2av = B::UNOP->new('rv2av', OPf_WANT_LIST | OPf_KIDS | OPf_REF | OPf_MOD, 0);
342              
343 0 0 0     0 $parent->first($rv2av) if $parent->can('first') and ${$parent->first} == $$padsv;
  0         0  
344 0 0 0     0 $parent->last($rv2av) if $parent->can('last') and ${$parent->last} == $$padsv;
  0         0  
345              
346 0         0 $padsv->flags(OPf_WANT_SCALAR | OPf_MOD);
347 0         0 $padsv->private($padsv->private & OPfDEREF_AV); # tells it to autovivify a reference if needed
348 0         0 $padsv->next($rv2av);
349 0         0 $padsv->sibling(0);
350              
351 0         0 $rv2av->first($padsv);
352 0         0 $rv2av->next($padsv_next);
353 0         0 $rv2av->sibling($padsv_sibling);
354              
355 0         0 $did_already{$$self}++;
356 0         0 $redo_reverse_indices->();
357              
358 302         1040 };
359              
360             my $insert_join = sub {
361              
362             # no warnings 'syntax'; # magic
363              
364             # print "debug: doing insert_join $lastpack $lastfile $lastline\n";
365              
366             # perl -MO=Concise -e 'my @foo = (1..20); my $foo = "bar" . @foo . "baz";'
367              
368             # 9 <;> nextstate(main 2 -e:1) v ->a
369             # g <2> sassign vKS/2 ->h
370             # e <2> concat[t7] sKS/2 ->f
371             # c <2> concat[t6] sK/2 ->d
372             # a <$> const(PV "bar") s ->b
373             # b <0> padav[@foo:1,3] s ->c <-- splice stuff in here
374             # d <$> const(PV "baz") s ->e
375             # f <0> padsv[$foo:2,3] sRM*/LVINTRO ->g
376              
377             # perl -MO=Concise
378             # my @foo = (1..20); print "bar" . join(${'$"'}, @foo), "baz";
379              
380             # 9 <;> nextstate(main 3 -:1) v ->a
381             # j <@> print vK ->k
382             # a <0> pushmark s ->b
383             # h <2> concat[t6] sK/2 ->i
384             # b <$> const(PV "bar") s ->c <-- * start
385             # g <@> join[t5] sK/2 ->h <-- replaces padav in tree
386             # c <0> pushmark s ->d <-- insert before padav in execution
387             # e <1> rv2sv sK/1 ->f
388             # d <$> const(PV "$\"") s ->e
389             # f <0> padav[@foo:1,3] l ->g
390             # i <$> const(PV "baz") s ->j
391              
392 1     1   2 my $padav = $self;
393 1 50       4 my $nextstate = $previous->{$$padav} or die "no previous"; # actually const 'bar' in the example
394 1         4 my $padav_next = $padav->next;
395 1         11 my $padav_sibling = $padav->sibling; # may be 0
396              
397 1         9 my $pushmark = B::OP->new('pushmark', OPf_WANT_SCALAR);
398 1         10 my $const = B::SVOP->new('const', OPf_WANT_SCALAR, '"');
399 1         8 my $rv2sv = B::UNOP->new('rv2sv', OPf_WANT_SCALAR | OPf_KIDS, 0);
400              
401             # have to build structure to avoid coredumps from ck_ routines! suck! redundant stuff
402 1         4 $pushmark->sibling($const); $const->sibling(0); # chain of siblings under $join
  1         4  
403 1         18 my $join = B::LISTOP->new('join', OPf_WANT_SCALAR | OPf_KIDS, $pushmark, $padav);
404              
405 1 50 33     7 $parent->first($join) if $parent->can('first') and ${$parent->first} == $$padav;
  1         7  
406 1 50 33     8 $parent->last($join) if $parent->can('last') and ${$parent->last} == $$padav;
  1         10  
407              
408 1         4 $nextstate->next($pushmark); # splice in
409 1 50 33     19 $nextstate->sibling($join) if $nextstate->can('sibling') and ${$nextstate->sibling} == $$padav;
  1         10  
410              
411 1         4 $pushmark->sibling($rv2sv);
412 1         3 $pushmark->next($const);
413              
414 1         3 $const->next($rv2sv);
415              
416 1         4 $rv2sv->sibling($padav);
417 1         3 $rv2sv->next($padav);
418 1         4 $rv2sv->first($const);
419              
420 1         9 $padav->sibling(0);
421 1         3 $padav->flags(OPf_WANT_LIST);
422 1         5 $padav->next($join);
423              
424 1         11 $join->private(2); # XXX - voodoo - to match code generated by perl - does this mean we join two things?
425 1         2 $lastpadtmp++; $lastpadtmp %= scalar @padtmps;
  1         2  
426             # XXX should alternate between two temps, or through the whole queue -
427             # not sure - all must be able to live on the stack at the same time though
428 1         9 $join->targ($padtmps[$lastpadtmp]);
429 1         3 $join->first($pushmark);
430 1         4 $join->last($padav);
431 1         3 $join->sibling($padav_sibling);
432 1         5 $join->next($padav_next); # splice out
433              
434 1         2 $did_already{$$self}++;
435 1         4 $redo_reverse_indices->();
436              
437 302         1207 };
438              
439             # hash or array variable used in scalar context other than as boolean or number:
440              
441 302 100 100     2695 goto not_padav unless $self->name() eq 'padav' or $self->name() eq 'padhv';
442 19 100       94 goto not_padav unless OPf_WANT_SCALAR == ($self->flags() & OPf_WANT);
443 9 100       34 goto not_padav if $self->flags & OPf_REF; # things like 'exists' want a ref
444 6 100       37 goto not_padav if exists $mathops->{$non_null_parent->name()};
445 4 50       27 goto not_padav if exists $boolops->{$non_null_parent->name()};
446 4 100       21 goto not_padav if exists $stringops->{$non_null_parent->name()};
447 3 50       11 goto not_padav if $did_already{$$self};
448              
449 3         8 $padav_to_ref->();
450              
451 302 100 100     2625 not_padav:
452              
453             # both subroutine and method calls:
454              
455             goto not_entersub unless $self->name() eq 'padav' or $self->name() eq 'padhv';
456 19 100       113 goto not_entersub unless $non_null_parent->name() eq 'entersub';
457 4 50       28 goto not_entersub unless OPf_WANT_LIST == ($self->flags() & OPf_WANT);
458 4 50       17 goto not_entersub if $did_already{$$self};
459 4         9 $padav_to_ref->();
460            
461 302 100       1647 not_entersub:
462              
463             # arrays should stringify when used in scalar context with a string op:
464              
465             goto not_string unless $self->name eq 'padav';
466 14 100       125 goto not_string unless exists $stringops->{$non_null_parent->name()};
467 1 50       7 goto not_string unless OPf_WANT_SCALAR == ($self->flags() & OPf_WANT);
468 1 50       5 goto not_string if $did_already{$$self};
469              
470 1 50       4 die 'Due to a limitation of B::Generate and this module you must declare several lexical variables: my($t1, $t2, $t3). ' .
471             'This is sadly required to use arrays in string context with Perl6::Contexts. ' unless @padtmps;
472              
473 1         4 $insert_join->();
474              
475 302         5532 not_string:
476              
477             return 0;
478              
479             }
480              
481             1;
482              
483             =pod
484              
485             =head1 NAME
486              
487             L - array and hash variables turn into references to themselves when
488             used in non-numeric scalar context or as function arguments
489              
490             =head1 SYNOPSIS
491              
492             my @foo = ( 1 .. 20 );
493             my $foo = @foo; # same as: my $foo = \@foo;
494             my $foo = 0 + @foo; # unchanged - length of @foo
495             $obj->some_method(10, 20, @foo); # same as: $obj->some_method(10, 20, \@foo);
496             some_function(10, 20, @foo); # same as: some_function(10, 20, \@foo);
497              
498             =head1 DESCRIPTION
499              
500             L makes Perl 5 behave more like Perl 6 with regard to the
501             array and hash variables as used as arguments to operators, method calls, and functions.
502              
503             This module doesn't add new syntax -- it merely changes the meaning of existing
504             syntax.
505             Using this module to make Perl 5 more like Perl 6 won't go very far towards
506             writing Perl 5 that will run under Perl 6 but it I help you get used to
507             some of the changes.
508              
509             To run legacy Perl 5 along side Perl 6, check out L or L.
510              
511             =head2 Context
512              
513             Perl 6 divides scalar context into boolean, numeric, string, and object context, among others.
514              
515             =head3 Reference Context
516              
517             Arrays and hashes used in reference context turn into a reference to themselves.
518             We assume reference context unless we know better. This vaguely approximates
519             Perl 6's behavior. For example, given a completely spurrious C<< my $foo = @bar >>,
520             we assume that C<$foo> should be a reference to C<@bar>.
521              
522             =head3 Numeric Context
523              
524             Arrays used in numeric context return their size, as in Perl 5.
525             Perl 6 uses the C<+> prefix or C, C, or C keywords to force numeric context.
526             We don't have those keywords (yet), but C<+> and C do the trick for now.
527             Numeric context is also supplied by math related operators such as C<->, C<*>, C,
528             and so on.
529              
530             Force numeric context to get the old Perl 5 behavior of counting the elements in an array or hash:
531              
532             scalar @arr;
533             0 + @arr;
534              
535             In Perl 6, the C<0> is redundant and undesireably ugly but it is required for our purposes so
536             I suggest using C instead.
537              
538             Note that hashes return internal memory allocation information when used in scalar context -
539             use C to count the number of items it contains.
540              
541             =head3 Boolean Context
542              
543             Boolean context formalizes the murky semantics of "zero but true" for Perl 6
544             but our implementation doesn't do anything to help with that.
545             Our boolean context is currently identical to Perl 5's scalar context
546             which is identical to numeric context and is provided by
547             C, C, C<&&>, C<||>, and other conditionls.
548              
549             =head3 String Context
550              
551             Perl 6 gives arrays, hashes, and objects, among other things, control over how they present themselves
552             when used as a string.
553             Perl 6 adds interpolation of hashes in quoted text, along with the arrays and scalars that
554             already interpolate in Perl 5.
555             Each variable can be extended with a trait to control the exact details of its presentation.
556             Perl 5 allows a minimal amount of presentation control with the global C<< $" >> variable.
557             See F's entry on C<< $" >> for details.
558             We don't try to interpolate hashes in strings but we do C on C<< $" >> to stringify
559             arrays when used as a string. The C<.> operator, for example, forces string context.
560              
561             use Perl6::Contexts;
562             my $t1; my $t2; my $t3;
563             my @arr = ( 1 .. 20 );
564             print '@arr: ' . @arr . "\n"; # note that . is used instead of comma
565              
566             C<.> forces string context on C<@arr> in this example.
567              
568             Or:
569              
570             use Perl6::Contexts;
571             my $t1; my $t2; my $t3;
572             my @arr = ( 1 .. 20 );
573             $" = '-';
574             @arr =~ m/15-16/ or die;
575              
576             C<=~> forces string context on C<@arr> in this example. That's a lot more useful
577             than matching on a string representing of the number of things in C<@arr>.
578              
579             Yes, the C things are needed to use arrays in string context. It's a long story.
580             See the B section for details if you're curious but it's a limitation I hope
581             to overcome soon. There must be one such variable allocated for each string context
582             use of an array in the single most complex expression in the module (and thus
583             is the sacrifice that must be paid homage to satisify the demons that make this module work).
584              
585             =head3 Context Summary
586              
587             This module cheats a bit in guessing context. Contexts do not propogate (yet) as
588             they do in Perl. Operators such as C<< || >> do not yet apply the context to their operands
589             that they themselves got from somewhere. The point of some contexts, such as boolean,
590             is entirely missed. In general, the Perl 6 rules and this module come closer to
591             the ideal of "do what I mean".
592              
593             =head2 Function Calls
594              
595             Hashes and arrays as function and method call arguments don't flatten by
596             default. Perl 6 uses the splat operator, C<*>, to flatten arrays and hashes sent
597             as arguents to functions.
598             Like Perl 6, we don't flatten implicitly either. Unlike Perl 6, explicit flattening is
599             kind of painful.
600              
601             use Perl6::Contexts;
602              
603             my @numbers = map int rand 100, 1 .. 100;
604             sub_that_wants_a_bunch_of_numbers(@numbers); # passes by reference - wrong
605             sub_that_wants_a_bunch_of_numbers(\@numbers); # same thing - wrong
606              
607             In order to flatten things for subroutines that actually want flattened
608             arrays, use one of these tricks:
609              
610             sub_that_wants_a_bunch_of_numbers(@numbers[0 .. $#numbers]);
611             sub_that_wants_a_bunch_of_numbers(@numbers->flatten());
612              
613             C<< ->flatten() >> requires F. See below. Perl 6's C<*> operator,
614             which forcefully unflattens arrays, is not available in Perl 5 or via
615             this module.
616              
617             Subroutines called by code subjected to the rules of F must
618             accept references to arrays and hashes I the array or hash in the
619             call to that subroutine was I flattened:
620              
621             use Perl6::Contexts;
622              
623             my @array = ( 1 .. 20 );
624             sub_that_wants_an_array_ref(@array);
625              
626             sub sub_that_wants_an_array_ref {
627             my $arrayref = shift; # @array turned into a reference
628             my @array = @$arrayref; # or use an autobox trick if you like
629             }
630              
631             This applies even if the subroutine or method is in another package entirely.
632             Note that the requirement that C<@$arrayref> be written that way and not
633             C<$arrayref> is an incompleteness of this module though obviously we aren't
634             going to munge modules that don't use us.
635             See the F tricks below and of course C<$arrayref> may be used directly
636             as the array reference that it is.
637              
638             =head2 autobox Interopation
639              
640             This module works with L. Normally L requires a reference, a scalar, a number, a string,
641             or a code reference, which excludes arrays and hashes:
642              
643             use autobox;
644             use autobox::Core;
645             my @arr = ( 1 .. 20);
646             @arr->sum->print; # doesn't work without Perl6::Contexts
647             (\@arr)->sum->print; # works without Perl6::Contexts but ugly
648              
649             Same goes for hashes.
650             (While this is a fluke side effect of what we're doing I was aware of the
651             consequence early on and it was a great motiviation to create this module, so
652             F integration is a feature beyond any doubt.)
653              
654             Often you'll want arrays and hashes to flatten when passed as arguments:
655              
656             use Perl6::Contexts;
657              
658             my @numbers = map int rand 100, 1 .. 100;
659             sub_that_wants_a_bunch_of_numbers(@numbers); # passes by reference - wrong
660              
661             F and F may be used to force array flattening:
662              
663             use Perl6::Contexts;
664             use autobox;
665             use autobox::Core;
666              
667             my @numbers = map int rand 100, 1 .. 100;
668             sub_that_wants_a_bunch_of_numbers(@numbers->flatten); # explicit flattening
669              
670             To accomplish this without F, you may take a slice of the entire array:
671              
672             use Perl6::Contexts;
673              
674             my @numbers = map int rand 100, 1 .. 100;
675             sub_that_wants_a_bunch_of_numbers(@numbers[0 .. $#numbers]); # ugly but works
676              
677             =head1 BUGS
678              
679             Most of these bugs are fixable but why should I bother if no one is actually using
680             this module?
681             Want a bug fixes?
682             Email me.
683             A little encouragement goes a long way.
684              
685             Until I get around to finishing reworking C, C needs
686             line 940 of C changed to read
687             C (the word C and an understore should be inserted).
688             This is in order to build C on newer Perls.
689              
690             C<..> and C<...> aren't yet recognized numeric operators.
691              
692             C<@arr = ( @arr2, @arr3, @arr4 )> should not flatten (I think) but currently does.
693              
694             Scalar variables used in conditionals (such as C and C) don't
695             dereference themselves and reference values are always true
696             (unless you do something special).
697             Hence this will always die:
698              
699             use Perl6::Contexts;
700             my @arr = ( ); # completely empty arrays evaluate false
701             my $arrref = @arr; # takes a reference
702             die if $arrref; # always dies - ERROR
703              
704             You must use C< autobox > and C< autobox::Core > and write C<< die if $arrref->flatten() >>,
705             or else write the old Perl 5 stand by, C< @$arrref >.
706              
707             C, C, C, C, C, C, C, C,
708             C, and C issue compile time warnings when used on a scalar even
709             though this scalar could only possibly be a reference.
710              
711             push $arrref, 1;
712              
713             # diagnostic: Type of arg 1 to push must be array (not scalar dereference)
714              
715             Perl 6 handles this correctly. Perl 5 could with replacement versions of
716             those statements written in Perl. Perhaps in the next version this module will.
717             Of course, it would be nice if the core did the "right thing" ;)
718              
719             The unary C<*> operator doesn't flatten lists as it does in Perl 6.
720             Instead, F and C<< ->flatten >> must be used for this, or
721             synonymously, C<< ->elements >>.
722             As far as I know, this is unfixable without resorting to a source filter,
723             which I won't do in this module.
724              
725             C is considered to provide numeric context.
726             This is not consistent
727             with Perl 6, where C, C, C, C, C, C, and C
728             generate contexts, much like C does in Perl 5.
729             This module should, but doesn't, export those keywords.
730              
731             While C<0 + @arr> accidentally works to put C<@arr> in numeric context and get its length,
732             no unary C<~> (yet) exists to force string context (though it could - it would mean no
733             more negating strings full of bits without calling a function in another module to do it).
734              
735             C<< my @array = $arrayref >> should, but doesn't, dereference C<$arrayref> and dump its
736             contents into C<@array>.
737             This can, and should, be done but I haven't gotten to it yet.
738              
739             Hashes in strings should interpolate but that's outside the scope of this module.
740             See L for an implementation.
741              
742             Making users create temporaries is a kludge as ugly as any.
743             I plan to roll this ability into F.
744             Why are C, C, and so on, required?
745             Perl associates nameless lexical variables with operations to speed up the stack machine.
746             Each operation has its own virtually private scalar value, array value, hash value, or so on,
747             that it can push to the stack any time it likes without having to allocate it. Next time the
748             instruction runs again it knows that it can reuse the same variable. F isn't
749             able to allocate these for instructions so I have to use preexisting named variables.
750              
751             =head1 HISTORY
752              
753             0.3 Fixes a serious bug where only the first of any number of arrays or hashes passed
754             to a subroutine would referencify. The logic to loop through through the bytecode
755             couldn't handle the bytecode changing out from under it and it lost its place.
756             Added several todo list items to the top of the file for myself and those curious
757             about possible future development.
758              
759             0.2 Fixes a show stopper bug that broke C and method calls, where the same
760             array or hash would referencify twice. Code with anonymous subroutines
761             triggered a fatal bug.
762              
763             Versions fixing bugs I've found and adding features I think of will increment the minor
764             version number. 1.0 will be released after a sufficient amount of user feedback suggestions
765             that I'm not as far off in la-la land as I might be for all I know.
766             This la-la land caveat applies to the Perl 6 specification as well, which I am doubtlessly botching.
767              
768             =head1 SEE ALSO
769              
770             L associates methods with primitive types allowing
771             more complex APIs for types than would be reasonable to
772             create built-in functions for. Fing also
773             simplifies complex expressions that would require a lot
774             of parenthesis by allowing the expression to be arranged
775             into more a logical structure.
776              
777             L compliments F with wrappers for most
778             built-in functions, some statements, some functionalish methods
779             from core modules, and some Perl 6-ish things.
780              
781             Perl 6 is able to take C<$arrayref[0]> to mean C<$arrayref.[0]> which
782             is C<< $arrayref->[0] >> in Perl 5. This module won't get you that
783             but see L.
784              
785             L gives Perl 5 subroutines Perl 6-like information about the
786             context they execute in, including the number of result values
787             expected, boolean context, C, and various kinds of
788             reference contexts. It is a generalized replacement for the
789             built-in F function.
790              
791             L represents Perl internal data structures (including and especially
792             bytecode instructions for the virtual machine) as Perl objects within
793             F itself. L extends L with the capability to modify
794             this bytecode from within the running program (!!!). This module uses
795             these two modules to do what it does. L served as a reference,
796             and code was stolen from L, L, and L
797             (but with implicit permission - yes, Free Software programmers do steal
798             but never uninvited - seriously, I owe a debt of gratitude to those
799             whose work I've built on, especially Simon Cozens and Malcolm Beattie in this case).
800              
801             L attempts to document the Perl
802             internals I'm prodding so bluntly.
803              
804             =head1 AUTHOR
805              
806             SWALTERS, L
807              
808             =cut
809              
810             __END__