home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / perl / Context.pm < prev    next >
Encoding:
Perl POD Document  |  2004-01-30  |  26.3 KB  |  792 lines

  1. #============================================================= -*-Perl-*-
  2. #
  3. # Template::Stash::Context
  4. #
  5. # DESCRIPTION
  6. #   This is an alternate stash object which includes a patch from 
  7. #   Craig Barratt to implement various new virtual methods to allow
  8. #   dotted template variable to denote if object methods and subroutines
  9. #   should be called in scalar or list context.  It adds a little overhead
  10. #   to each stash call and I'm a little wary of doing that.  So for now,
  11. #   it's implemented as a separate stash module which will allow us to 
  12. #   test it out, benchmark it and switch it in or out as we require.
  13. #
  14. #   This is what Craig has to say about it:
  15. #   
  16. #   Here's a better set of features for the core.  Attached is a new version
  17. #   of Stash.pm (based on TT2.02) that:
  18. #   
  19. #     - supports the special op "scalar" that forces scalar context on
  20. #       function calls, eg:
  21. #   
  22. #           cgi.param("foo").scalar
  23. #   
  24. #       calls cgi.param("foo") in scalar context (unlike my wimpy
  25. #       scalar op from last night).  Array context is the default.
  26. #   
  27. #       With non-function operands, scalar behaves like the perl
  28. #       version (eg: no-op for scalar, size for arrays, etc).
  29. #   
  30. #     - supports the special op "ref" that behaves like the perl ref.
  31. #       If applied to a function the function is not called.  Eg:
  32. #   
  33. #           cgi.param("foo").ref
  34. #   
  35. #       does *not* call cgi.param and evaluates to "CODE".  Similarly,
  36. #       HASH.ref, ARRAY.ref return what you expect.
  37. #   
  38. #     - adds a new scalar and list op called "array" that is a no-op for
  39. #       arrays and promotes scalars to one-element arrays.
  40. #   
  41. #     - allows scalar ops to be applied to arrays and hashes in place,
  42. #       eg: ARRAY.repeat(3) repeats each element in place.
  43. #   
  44. #     - allows list ops to be applied to scalars by promoting the scalars
  45. #       to one-element arrays (like an implicit "array").  So you can
  46. #       do things like SCALAR.size, SCALAR.join and get a useful result.
  47. #   
  48. #       This also means you can now use x.0 to safely get the first element
  49. #       whether x is an array or scalar.
  50. #   
  51. #   The new Stash.pm passes the TT2.02 test suite.  But I haven't tested the
  52. #   new features very much.  One nagging implementation problem is that the
  53. #   "scalar" and "ref" ops have higher precedence than user variable names.
  54. #   
  55. # AUTHORS
  56. #   Andy Wardley  <abw@kfs.org>
  57. #   Craig Barratt <craig@arraycomm.com>
  58. #
  59. # COPYRIGHT
  60. #   Copyright (C) 1996-2001 Andy Wardley.  All Rights Reserved.
  61. #   Copyright (C) 1998-2001 Canon Research Centre Europe Ltd.
  62. #
  63. #   This module is free software; you can redistribute it and/or
  64. #   modify it under the same terms as Perl itself.
  65. #
  66. #----------------------------------------------------------------------------
  67. #
  68. # $Id: Context.pm,v 1.58 2004/01/13 16:21:52 abw Exp $
  69. #
  70. #============================================================================
  71.  
  72. package Template::Stash::Context;
  73.  
  74. require 5.004;
  75.  
  76. use strict;
  77. use Template::Stash;
  78. use vars qw( $VERSION $DEBUG $ROOT_OPS $SCALAR_OPS $HASH_OPS $LIST_OPS );
  79.  
  80. $VERSION = sprintf("%d.%02d", q$Revision: 1.58 $ =~ /(\d+)\.(\d+)/);
  81.  
  82.  
  83. #========================================================================
  84. #                    -- PACKAGE VARIABLES AND SUBS --
  85. #========================================================================
  86.  
  87. #------------------------------------------------------------------------
  88. # copy virtual methods from those in the regular Template::Stash
  89. #------------------------------------------------------------------------
  90.  
  91. $ROOT_OPS = { 
  92.     %$Template::Stash::ROOT_OPS,
  93.     defined $ROOT_OPS ? %$ROOT_OPS : (),
  94. };
  95.  
  96. $SCALAR_OPS = { 
  97.     %$Template::Stash::SCALAR_OPS,
  98.     'array' => sub { return [$_[0]] },
  99.     defined $SCALAR_OPS ? %$SCALAR_OPS : (),
  100. };
  101.  
  102. $LIST_OPS = { 
  103.     %$Template::Stash::LIST_OPS,
  104.     'array' => sub { return $_[0] },
  105.     defined $LIST_OPS ? %$LIST_OPS : (),
  106. };
  107.             
  108. $HASH_OPS = { 
  109.     %$Template::Stash::HASH_OPS,
  110.     defined $HASH_OPS ? %$HASH_OPS : (),
  111. };
  112.  
  113.  
  114.  
  115. #========================================================================
  116. #                      -----  CLASS METHODS -----
  117. #========================================================================
  118.  
  119. #------------------------------------------------------------------------
  120. # new(\%params)
  121. #
  122. # Constructor method which creates a new Template::Stash object.
  123. # An optional hash reference may be passed containing variable 
  124. # definitions that will be used to initialise the stash.
  125. #
  126. # Returns a reference to a newly created Template::Stash.
  127. #------------------------------------------------------------------------
  128.  
  129. sub new {
  130.     my $class  = shift;
  131.     my $params = ref $_[0] eq 'HASH' ? shift(@_) : { @_ };
  132.  
  133.     my $self   = {
  134.     global  => { },
  135.     %$params,
  136.     %$ROOT_OPS,
  137.     '_PARENT' => undef,
  138.     };
  139.  
  140.     bless $self, $class;
  141. }
  142.  
  143.  
  144. #========================================================================
  145. #                   -----  PUBLIC OBJECT METHODS -----
  146. #========================================================================
  147.  
  148. #------------------------------------------------------------------------
  149. # clone(\%params)
  150. #
  151. # Creates a copy of the current stash object to effect localisation 
  152. # of variables.  The new stash is blessed into the same class as the 
  153. # parent (which may be a derived class) and has a '_PARENT' member added
  154. # which contains a reference to the parent stash that created it
  155. # ($self).  This member is used in a successive declone() method call to
  156. # return the reference to the parent.
  157. # A parameter may be provided which should reference a hash of 
  158. # variable/values which should be defined in the new stash.  The 
  159. # update() method is called to define these new variables in the cloned
  160. # stash.
  161. #
  162. # Returns a reference to a cloned Template::Stash.
  163. #------------------------------------------------------------------------
  164.  
  165. sub clone {
  166.     my ($self, $params) = @_;
  167.     $params ||= { };
  168.  
  169.     # look out for magical 'import' argument which imports another hash
  170.     my $import = $params->{ import };
  171.     if (defined $import && UNIVERSAL::isa($import, 'HASH')) {
  172.     delete $params->{ import };
  173.     }
  174.     else {
  175.     undef $import;
  176.     }
  177.  
  178.     my $clone = bless { 
  179.     %$self,            # copy all parent members
  180.     %$params,        # copy all new data
  181.         '_PARENT' => $self,     # link to parent
  182.     }, ref $self;
  183.     
  184.     # perform hash import if defined
  185.     &{ $HASH_OPS->{ import }}($clone, $import)
  186.     if defined $import;
  187.  
  188.     return $clone;
  189. }
  190.  
  191.     
  192. #------------------------------------------------------------------------
  193. # declone($export) 
  194. #
  195. # Returns a reference to the PARENT stash.  When called in the following
  196. # manner:
  197. #    $stash = $stash->declone();
  198. # the reference count on the current stash will drop to 0 and be "freed"
  199. # and the caller will be left with a reference to the parent.  This 
  200. # contains the state of the stash before it was cloned.  
  201. #------------------------------------------------------------------------
  202.  
  203. sub declone {
  204.     my $self = shift;
  205.     $self->{ _PARENT } || $self;
  206. }
  207.  
  208.  
  209. #------------------------------------------------------------------------
  210. # get($ident)
  211. # Returns the value for an variable stored in the stash.  The variable
  212. # may be specified as a simple string, e.g. 'foo', or as an array 
  213. # reference representing compound variables.  In the latter case, each
  214. # pair of successive elements in the list represent a node in the 
  215. # compound variable.  The first is the variable name, the second a 
  216. # list reference of arguments or 0 if undefined.  So, the compound 
  217. # variable [% foo.bar('foo').baz %] would be represented as the list
  218. # [ 'foo', 0, 'bar', ['foo'], 'baz', 0 ].  Returns the value of the
  219. # identifier or an empty string if undefined.  Errors are thrown via
  220. # die().
  221. #------------------------------------------------------------------------
  222.  
  223. sub get {
  224.     my ($self, $ident, $args) = @_;
  225.     my ($root, $result);
  226.     $root = $self;
  227.  
  228.     if (ref $ident eq 'ARRAY'
  229.     || ($ident =~ /\./) 
  230.     && ($ident = [ map { s/\(.*$//; ($_, 0) } split(/\./, $ident) ])) {
  231.     my $size = $#$ident;
  232.  
  233.     # if $ident is a list reference, then we evaluate each item in the 
  234.     # identifier against the previous result, using the root stash 
  235.     # ($self) as the first implicit 'result'...
  236.  
  237.     foreach (my $i = 0; $i <= $size; $i += 2) {
  238.         if ( $i + 2 <= $size && ($ident->[$i+2] eq "scalar"
  239.                                     || $ident->[$i+2] eq "ref") ) {
  240.                 $result = $self->_dotop($root, @$ident[$i, $i+1], 0,
  241.                                         $ident->[$i+2]);
  242.                 $i += 2;
  243.         } else {
  244.                 $result = $self->_dotop($root, @$ident[$i, $i+1]);
  245.             }
  246.         last unless defined $result;
  247.         $root = $result;
  248.     }
  249.     }
  250.     else {
  251.     $result = $self->_dotop($root, $ident, $args);
  252.     }
  253.  
  254.     return defined $result ? $result : '';
  255. }
  256.  
  257.  
  258. #------------------------------------------------------------------------
  259. # set($ident, $value, $default)
  260. #
  261. # Updates the value for a variable in the stash.  The first parameter
  262. # should be the variable name or array, as per get().  The second 
  263. # parameter should be the intended value for the variable.  The third,
  264. # optional parameter is a flag which may be set to indicate 'default'
  265. # mode.  When set true, the variable will only be updated if it is
  266. # currently undefined or has a false value.  The magical 'IMPORT'
  267. # variable identifier may be used to indicate that $value is a hash
  268. # reference whose values should be imported.  Returns the value set,
  269. # or an empty string if not set (e.g. default mode).  In the case of 
  270. # IMPORT, returns the number of items imported from the hash.
  271. #------------------------------------------------------------------------
  272.  
  273. sub set {
  274.     my ($self, $ident, $value, $default) = @_;
  275.     my ($root, $result, $error);
  276.  
  277.     $root = $self;
  278.  
  279.     ELEMENT: {
  280.     if (ref $ident eq 'ARRAY'
  281.         || ($ident =~ /\./) 
  282.         && ($ident = [ map { s/\(.*$//; ($_, 0) }
  283.                split(/\./, $ident) ])) {
  284.  
  285.         # a compound identifier may contain multiple elements (e.g. 
  286.         # foo.bar.baz) and we must first resolve all but the last, 
  287.         # using _dotop() with the $lvalue flag set which will create 
  288.         # intermediate hashes if necessary...
  289.         my $size = $#$ident;
  290.         foreach (my $i = 0; $i < $size - 2; $i += 2) {
  291.         $result = $self->_dotop($root, @$ident[$i, $i+1], 1);
  292.         last ELEMENT unless defined $result;
  293.         $root = $result;
  294.         }
  295.  
  296.         # then we call _assign() to assign the value to the last element
  297.         $result = $self->_assign($root, @$ident[$size-1, $size], 
  298.                      $value, $default);
  299.     }
  300.     else {
  301.         $result = $self->_assign($root, $ident, 0, $value, $default);
  302.     }
  303.     }
  304.  
  305.     return defined $result ? $result : '';
  306. }
  307.  
  308.  
  309. #------------------------------------------------------------------------
  310. # getref($ident)
  311. # Returns a "reference" to a particular item.  This is represented as a 
  312. # closure which will return the actual stash item when called.  
  313. # WARNING: still experimental!
  314. #------------------------------------------------------------------------
  315.  
  316. sub getref {
  317.     my ($self, $ident, $args) = @_;
  318.     my ($root, $item, $result);
  319.     $root = $self;
  320.  
  321.     if (ref $ident eq 'ARRAY') {
  322.     my $size = $#$ident;
  323.  
  324.     foreach (my $i = 0; $i <= $size; $i += 2) {
  325.         ($item, $args) = @$ident[$i, $i + 1]; 
  326.         last if $i >= $size - 2;  # don't evaluate last node
  327.         last unless defined 
  328.         ($root = $self->_dotop($root, $item, $args));
  329.     }
  330.     }
  331.     else {
  332.     $item = $ident;
  333.     }
  334.  
  335.     if (defined $root) {
  336.         return sub { my @args = (@{$args||[]}, @_);
  337.              $self->_dotop($root, $item, \@args);
  338.          }
  339.     }
  340.     else {
  341.     return sub { '' };
  342.     }
  343. }
  344.  
  345.  
  346.  
  347.  
  348. #------------------------------------------------------------------------
  349. # update(\%params)
  350. #
  351. # Update multiple variables en masse.  No magic is performed.  Simple
  352. # variable names only.
  353. #------------------------------------------------------------------------
  354.  
  355. sub update {
  356.     my ($self, $params) = @_;
  357.  
  358.     # look out for magical 'import' argument to import another hash
  359.     my $import = $params->{ import };
  360.     if (defined $import && UNIVERSAL::isa($import, 'HASH')) {
  361.     @$self{ keys %$import } = values %$import;
  362.     delete $params->{ import };
  363.     }
  364.  
  365.     @$self{ keys %$params } = values %$params;
  366. }
  367.  
  368.  
  369. #========================================================================
  370. #                  -----  PRIVATE OBJECT METHODS -----
  371. #========================================================================
  372.  
  373. #------------------------------------------------------------------------
  374. # _dotop($root, $item, \@args, $lvalue, $nextItem)
  375. #
  376. # This is the core 'dot' operation method which evaluates elements of 
  377. # variables against their root.  All variables have an implicit root 
  378. # which is the stash object itself (a hash).  Thus, a non-compound 
  379. # variable 'foo' is actually '(stash.)foo', the compound 'foo.bar' is
  380. # '(stash.)foo.bar'.  The first parameter is a reference to the current
  381. # root, initially the stash itself.  The second parameter contains the 
  382. # name of the variable element, e.g. 'foo'.  The third optional
  383. # parameter is a reference to a list of any parenthesised arguments 
  384. # specified for the variable, which are passed to sub-routines, object 
  385. # methods, etc.  The final parameter is an optional flag to indicate 
  386. # if this variable is being evaluated on the left side of an assignment
  387. # (e.g. foo.bar.baz = 10).  When set true, intermediated hashes will 
  388. # be created (e.g. bar) if necessary.  
  389. #
  390. # Returns the result of evaluating the item against the root, having
  391. # performed any variable "magic".  The value returned can then be used
  392. # as the root of the next _dotop() in a compound sequence.  Returns
  393. # undef if the variable is undefined.
  394. #------------------------------------------------------------------------
  395.  
  396. sub _dotop {
  397.     my ($self, $root, $item, $args, $lvalue, $nextItem) = @_;
  398.     my $rootref = ref $root;
  399.     my ($value, @result, $ret, $retVal);
  400.     $nextItem ||= "";
  401.     my $scalarContext = 1 if ( $nextItem eq "scalar" );
  402.     my $returnRef = 1     if ( $nextItem eq "ref" );
  403.  
  404.     $args ||= [ ];
  405.     $lvalue ||= 0;
  406.  
  407. #    print STDERR "_dotop(root=$root, item=$item, args=[@$args])\n"
  408. #    if $DEBUG;
  409.  
  410.     # return undef without an error if either side of the dot is unviable
  411.     # or if an attempt is made to access a private member, starting _ or .
  412.     return undef
  413.     unless defined($root) and defined($item) and $item !~ /^[\._]/;
  414.  
  415.     if (ref(\$root) eq "SCALAR" && !$lvalue &&
  416.             (($value = $LIST_OPS->{ $item }) || $item =~ /^-?\d+$/) ) {
  417.         #
  418.         # Promote scalar to one element list, to be processed below.
  419.         #
  420.         $rootref = 'ARRAY';
  421.         $root = [$root];
  422.     }
  423.     if ($rootref eq __PACKAGE__ || $rootref eq 'HASH') {
  424.  
  425.     # if $root is a regular HASH or a Template::Stash kinda HASH (the 
  426.     # *real* root of everything).  We first lookup the named key 
  427.     # in the hash, or create an empty hash in its place if undefined
  428.     # and the $lvalue flag is set.  Otherwise, we check the HASH_OPS
  429.     # pseudo-methods table, calling the code if found, or return undef.
  430.  
  431.     if (defined($value = $root->{ $item })) {
  432.             ($ret, $retVal, @result) = _dotop_return($value, $args, $returnRef,
  433.                                                      $scalarContext);
  434.             return $retVal if ( $ret );                     ## RETURN
  435.         }
  436.     elsif ($lvalue) {
  437.         # we create an intermediate hash if this is an lvalue
  438.         return $root->{ $item } = { };            ## RETURN
  439.     }
  440.     elsif ($value = $HASH_OPS->{ $item }) {
  441.         @result = &$value($root, @$args);            ## @result
  442.     }
  443.     elsif (ref $item eq 'ARRAY') {
  444.         # hash slice
  445.         return [@$root{@$item}];                       ## RETURN
  446.     }
  447.     elsif ($value = $SCALAR_OPS->{ $item }) {
  448.         #
  449.         # Apply scalar ops to every hash element, in place.
  450.         #
  451.         foreach my $key ( keys %$root ) {
  452.                 $root->{$key} = &$value($root->{$key}, @$args);
  453.             }
  454.     }
  455.     }
  456.     elsif ($rootref eq 'ARRAY') {
  457.  
  458.     # if root is an ARRAY then we check for a LIST_OPS pseudo-method 
  459.     # (except for l-values for which it doesn't make any sense)
  460.     # or return the numerical index into the array, or undef
  461.  
  462.     if (($value = $LIST_OPS->{ $item }) && ! $lvalue) {
  463.         @result = &$value($root, @$args);            ## @result
  464.     }
  465.     elsif (($value = $SCALAR_OPS->{ $item }) && ! $lvalue) {
  466.         #
  467.         # Apply scalar ops to every array element, in place.
  468.         #
  469.         for ( my $i = 0 ; $i < @$root ; $i++ ) {
  470.                 $root->[$i] = &$value($root->[$i], @$args); ## @result
  471.             }
  472.     }
  473.     elsif ($item =~ /^-?\d+$/) {
  474.         $value = $root->[$item];
  475.             ($ret, $retVal, @result) = _dotop_return($value, $args, $returnRef,
  476.                                                      $scalarContext);
  477.             return $retVal if ( $ret );                     ## RETURN
  478.     }
  479.         elsif (ref $item eq 'ARRAY' ) {
  480.             # array slice
  481.             return [@$root[@$item]];                        ## RETURN
  482.         }
  483.     }
  484.  
  485.     # NOTE: we do the can-can because UNIVSERAL::isa($something, 'UNIVERSAL')
  486.     # doesn't appear to work with CGI, returning true for the first call
  487.     # and false for all subsequent calls. 
  488.  
  489.     elsif (ref($root) && UNIVERSAL::can($root, 'can')) {
  490.  
  491.     # if $root is a blessed reference (i.e. inherits from the 
  492.     # UNIVERSAL object base class) then we call the item as a method.
  493.     # If that fails then we try to fallback on HASH behaviour if 
  494.     # possible.
  495.         return ref $root->can($item) if ( $returnRef );       ## RETURN
  496.     eval {
  497.             @result = $scalarContext ? scalar $root->$item(@$args)
  498.                                      : $root->$item(@$args);  ## @result
  499.         };
  500.  
  501.     if ($@) {
  502.         # failed to call object method, so try some fallbacks
  503.         if (UNIVERSAL::isa($root, 'HASH')
  504.                     && defined($value = $root->{ $item })) {
  505.                 ($ret, $retVal, @result) = _dotop_return($value, $args,
  506.                                                     $returnRef, $scalarContext);
  507.                 return $retVal if ( $ret );                     ## RETURN
  508.         }
  509.         elsif (UNIVERSAL::isa($root, 'ARRAY') 
  510.            && ($value = $LIST_OPS->{ $item })) {
  511.         @result = &$value($root, @$args);
  512.         }
  513.         else {
  514.         @result = (undef, $@);
  515.         }
  516.     }
  517.     }
  518.     elsif (($value = $SCALAR_OPS->{ $item }) && ! $lvalue) {
  519.  
  520.     # at this point, it doesn't look like we've got a reference to
  521.     # anything we know about, so we try the SCALAR_OPS pseudo-methods
  522.     # table (but not for l-values)
  523.  
  524.     @result = &$value($root, @$args);            ## @result
  525.     }
  526.     elsif ($self->{ _DEBUG }) {
  527.     die "don't know how to access [ $root ].$item\n";   ## DIE
  528.     }
  529.     else {
  530.     @result = ();
  531.     }
  532.  
  533.     # fold multiple return items into a list unless first item is undef
  534.     if (defined $result[0]) {
  535.     return ref(@result > 1 ? [ @result ] : $result[0])
  536.                                             if ( $returnRef );  ## RETURN
  537.     if ( $scalarContext ) {
  538.             return scalar @result if ( @result > 1 );           ## RETURN
  539.             return scalar(@{$result[0]}) if ( ref $result[0] eq "ARRAY" );
  540.             return scalar(%{$result[0]}) if ( ref $result[0] eq "HASH" );
  541.             return $result[0];                                  ## RETURN
  542.         } else {
  543.             return @result > 1 ? [ @result ] : $result[0];      ## RETURN
  544.         }
  545.     }
  546.     elsif (defined $result[1]) {
  547.     die $result[1];                        ## DIE
  548.     }
  549.     elsif ($self->{ _DEBUG }) {
  550.     die "$item is undefined\n";                ## DIE
  551.     }
  552.  
  553.     return undef;
  554. }
  555.  
  556. #------------------------------------------------------------------------
  557. # ($ret, $retVal, @result) = _dotop_return($value, $args, $returnRef,
  558. #                                          $scalarContext);
  559. #
  560. # Handle the various return processing for _dotop
  561. #------------------------------------------------------------------------
  562. sub _dotop_return
  563. {
  564.     my($value, $args, $returnRef, $scalarContext) = @_;
  565.     my(@result);
  566.  
  567.     return (1, ref $value) if ( $returnRef );                     ## RETURN
  568.     if ( $scalarContext ) {
  569.         return (1, scalar(@$value)) if ref $value eq 'ARRAY';     ## RETURN
  570.         return (1, scalar(%$value)) if ref $value eq 'HASH';      ## RETURN
  571.         return (1, scalar($value))  unless ref $value eq 'CODE';  ## RETURN;
  572.         @result = scalar &$value(@$args)                          ## @result;
  573.     } else {
  574.         return (1, $value) unless ref $value eq 'CODE';           ## RETURN
  575.         @result = &$value(@$args);                                ## @result
  576.     }
  577.     return (0, undef, @result);
  578. }
  579.  
  580.  
  581. #------------------------------------------------------------------------
  582. # _assign($root, $item, \@args, $value, $default)
  583. #
  584. # Similar to _dotop() above, but assigns a value to the given variable
  585. # instead of simply returning it.  The first three parameters are the
  586. # root item, the item and arguments, as per _dotop(), followed by the 
  587. # value to which the variable should be set and an optional $default
  588. # flag.  If set true, the variable will only be set if currently false
  589. # (undefined/zero)
  590. #------------------------------------------------------------------------
  591.  
  592. sub _assign {
  593.     my ($self, $root, $item, $args, $value, $default) = @_;
  594.     my $rootref = ref $root;
  595.     my $result;
  596.     $args ||= [ ];
  597.     $default ||= 0;
  598.  
  599. #    print(STDERR "_assign(root=$root, item=$item, args=[@$args], \n",
  600. #                         "value=$value, default=$default)\n")
  601. #    if $DEBUG;
  602.  
  603.     # return undef without an error if either side of the dot is unviable
  604.     # or if an attempt is made to update a private member, starting _ or .
  605.     return undef                        ## RETURN
  606.     unless $root and defined $item and $item !~ /^[\._]/;
  607.     
  608.     if ($rootref eq 'HASH' || $rootref eq __PACKAGE__) {
  609. #    if ($item eq 'IMPORT' && UNIVERSAL::isa($value, 'HASH')) {
  610. #        # import hash entries into root hash
  611. #        @$root{ keys %$value } = values %$value;
  612. #        return '';                        ## RETURN
  613. #    }
  614.     # if the root is a hash we set the named key
  615.     return ($root->{ $item } = $value)            ## RETURN
  616.         unless $default && $root->{ $item };
  617.     }
  618.     elsif ($rootref eq 'ARRAY' && $item =~ /^-?\d+$/) {
  619.     # or set a list item by index number
  620.     return ($root->[$item] = $value)            ## RETURN
  621.         unless $default && $root->{ $item };
  622.     }
  623.     elsif (UNIVERSAL::isa($root, 'UNIVERSAL')) {
  624.     # try to call the item as a method of an object
  625.     return $root->$item(@$args, $value);            ## RETURN
  626.     }
  627.     else {
  628.     die "don't know how to assign to [$root].[$item]\n";    ## DIE
  629.     }
  630.  
  631.     return undef;
  632. }
  633.  
  634.  
  635. #------------------------------------------------------------------------
  636. # _dump()
  637. #
  638. # Debug method which returns a string representing the internal state
  639. # of the object.  The method calls itself recursively to dump sub-hashes.
  640. #------------------------------------------------------------------------
  641.  
  642. sub _dump {
  643.     my $self   = shift;
  644.     my $indent = shift || 1;
  645.     my $buffer = '    ';
  646.     my $pad    = $buffer x $indent;
  647.     my $text   = '';
  648.     local $" = ', ';
  649.  
  650.     my ($key, $value);
  651.  
  652.  
  653.     return $text . "...excessive recursion, terminating\n"
  654.     if $indent > 32;
  655.  
  656.     foreach $key (keys %$self) {
  657.  
  658.     $value = $self->{ $key };
  659.     $value = '<undef>' unless defined $value;
  660.  
  661.     if (ref($value) eq 'ARRAY') {
  662.         $value = "$value [@$value]";
  663.     }
  664.     $text .= sprintf("$pad%-8s => $value\n", $key);
  665.     next if $key =~ /^\./;
  666.     if (UNIVERSAL::isa($value, 'HASH')) {
  667.         $text .= _dump($value, $indent + 1);
  668.     }
  669.     }
  670.     $text;
  671. }
  672.  
  673.  
  674. 1;
  675.  
  676. __END__
  677.  
  678.  
  679. #------------------------------------------------------------------------
  680. # IMPORTANT NOTE
  681. #   This documentation is generated automatically from source
  682. #   templates.  Any changes you make here may be lost.
  683. #   The 'docsrc' documentation source bundle is available for download
  684. #   from http://www.template-toolkit.org/docs.html and contains all
  685. #   the source templates, XML files, scripts, etc., from which the
  686. #   documentation for the Template Toolkit is built.
  687. #------------------------------------------------------------------------
  688.  
  689. =head1 NAME
  690.  
  691. Template::Stash::Context - Experimetal stash allowing list/scalar context definition
  692.  
  693. =head1 SYNOPSIS
  694.  
  695.     use Template;
  696.     use Template::Stash::Context;
  697.  
  698.     my $stash = Template::Stash::Context->new(\%vars);
  699.     my $tt2   = Template->new({ STASH => $stash });
  700.  
  701. =head1 DESCRIPTION
  702.  
  703. This is an alternate stash object which includes a patch from 
  704. Craig Barratt to implement various new virtual methods to allow
  705. dotted template variable to denote if object methods and subroutines
  706. should be called in scalar or list context.  It adds a little overhead
  707. to each stash call and I'm a little wary of applying that to the core
  708. default stash without investigating the effects first. So for now,
  709. it's implemented as a separate stash module which will allow us to 
  710. test it out, benchmark it and switch it in or out as we require.
  711.  
  712. This is what Craig has to say about it:
  713.  
  714. Here's a better set of features for the core.  Attached is a new version
  715. of Stash.pm (based on TT2.02) that:
  716.  
  717. * supports the special op "scalar" that forces scalar context on
  718. function calls, eg:
  719.  
  720.     cgi.param("foo").scalar
  721.  
  722. calls cgi.param("foo") in scalar context (unlike my wimpy
  723. scalar op from last night).  Array context is the default.
  724.  
  725. With non-function operands, scalar behaves like the perl
  726. version (eg: no-op for scalar, size for arrays, etc).
  727.  
  728. * supports the special op "ref" that behaves like the perl ref.
  729. If applied to a function the function is not called.  Eg:
  730.  
  731.     cgi.param("foo").ref
  732.  
  733. does *not* call cgi.param and evaluates to "CODE".  Similarly,
  734. HASH.ref, ARRAY.ref return what you expect.
  735.  
  736. * adds a new scalar and list op called "array" that is a no-op for
  737. arrays and promotes scalars to one-element arrays.
  738.  
  739. * allows scalar ops to be applied to arrays and hashes in place,
  740. eg: ARRAY.repeat(3) repeats each element in place.
  741.  
  742. * allows list ops to be applied to scalars by promoting the scalars
  743. to one-element arrays (like an implicit "array").  So you can
  744. do things like SCALAR.size, SCALAR.join and get a useful result.
  745.  
  746. This also means you can now use x.0 to safely get the first element
  747. whether x is an array or scalar.
  748.  
  749. The new Stash.pm passes the TT2.02 test suite.  But I haven't tested the
  750. new features very much.  One nagging implementation problem is that the
  751. "scalar" and "ref" ops have higher precedence than user variable names.
  752.  
  753. =head1 AUTHOR
  754.  
  755. Andy Wardley E<lt>abw@andywardley.comE<gt>
  756.  
  757. L<http://www.andywardley.com/|http://www.andywardley.com/>
  758.  
  759.  
  760.  
  761.  
  762. =head1 VERSION
  763.  
  764. 1.58, distributed as part of the
  765. Template Toolkit version 2.13, released on 30 January 2004.
  766.  
  767. =head1 COPYRIGHT
  768.  
  769.   Copyright (C) 1996-2004 Andy Wardley.  All Rights Reserved.
  770.   Copyright (C) 1998-2002 Canon Research Centre Europe Ltd.
  771.  
  772. This module is free software; you can redistribute it and/or
  773. modify it under the same terms as Perl itself.
  774.  
  775. =head1 SEE ALSO
  776.  
  777. L<Template::Stash|Template::Stash>
  778.  
  779. =cut
  780.  
  781. # Local Variables:
  782. # mode: perl
  783. # perl-indent-level: 4
  784. # indent-tabs-mode: nil
  785. # End:
  786. #
  787. # vim: expandtab shiftwidth=4:
  788.