File Coverage

lib/Devel/Trepan/CmdProcessor/Command/Eval.pm
Criterion Covered Total %
statement 78 146 53.4
branch 0 28 0.0
condition n/a
subroutine 26 30 86.6
pod 0 4 0.0
total 104 208 50.0


line stmt bran cond sub pod time code
1             # -*- coding: utf-8 -*-
2             # Copyright (C) 2011-2012, 2014-2015 Rocky Bernstein <rocky@cpan.org>
3 12     12   106 use warnings; use utf8;
  12     12   35  
  12     1   414  
  12     1   82  
  12         30  
  12         104  
  1         8  
  1         2  
  1         23  
  1         4  
  1         3  
  1         9  
4 12     12   330 use rlib '../../../..';
  12     1   37  
  12         72  
  1         22  
  1         3  
  1         5  
5              
6             package Devel::Trepan::CmdProcessor::Command::Eval;
7 12     12   4543 use if !@ISA, Devel::Trepan::CmdProcessor::Command ;
  12     1   31  
  12         78  
  1         318  
  1         3  
  1         4  
8             unless (@ISA) {
9 12     12   150 eval <<'EOE';
  12     12   30  
  12     12   872  
  12     12   82  
  12     12   34  
  12     12   728  
  12         74  
  12         31  
  12         570  
  12         82  
  12         25  
  12         591  
  12         72  
  12         28  
  12         535  
  12         77  
  12         29  
  12         657  
10             use constant ALIASES => qw(eval? eval@ eval% eval$ eval@? @ % $ p);
11             use constant CATEGORY => 'data';
12             use constant SHORT_HELP => 'Run code in the current context';
13             use constant NEED_STACK => 0;
14             use constant MIN_ARGS => 0; # Need at least this many
15             use constant MAX_ARGS => undef; # Need at most this many - undef -> unlimited.
16             EOE
17             }
18 12     12   2272 use strict;
  12     1   35  
  12         324  
  1         55  
  1         2  
  1         17  
19 12     12   76 use Devel::Trepan::Util;
  12     1   30  
  12         1691  
  1         7  
  1         2  
  1         128  
20              
21 12     12   90 use vars qw(@ISA); @ISA = @CMD_ISA;
  12     1   32  
  12         679  
  1         7  
  1         2  
  1         46  
22 12     12   102 use vars @CMD_VARS; # Value inherited from parent
  12     1   34  
  12         1786  
  1         5  
  1         2  
  1         123  
23              
24             our $NAME = set_name();
25             =head2 Synopsis:
26              
27             =cut
28             our $HELP = <<'HELP';
29             =pod
30              
31             B<eval>[B<@$>][B<?>] [I<Perl-code>]
32              
33             Run I<Perl-code> in the context of the current frame.
34              
35             If no string is given after the command "eval", we run the string from
36             the current source code about to be run. If the command ends ? (via an
37             alias) and no string is given we will the perform the translations:
38              
39             {if|elsif|unless} (expr) [{] => expr
40             {until|while} (expr) [{] => expr
41             return expr [;] => expr
42             {my|local|our} (expr1, expr2) = (v1,v2);
43             => (expr1, expr2) = (v1,v2)
44             {my|local|our} var = expr ; => expr
45             given expr => expr
46             sub fn(params) => (params)
47             var = expr => expr
48              
49             The above is done via regular expression. No fancy parsing is done, say,
50             to look to see if I<expr> is split across a line or whether var an assigment
51             might have multiple variables on the left-hand side.
52              
53             The value of the expression is stored into global array I<@DB:D> so it
54             may be used again easily.
55              
56             Normally I<eval> assumes you are typing a statement, not an expression;
57             the result is a scalar value. However you can force the type of the result
58             by adding the appropriate sigil C<@>, C<%>, or C<$>.
59              
60             =head2 Examples:
61              
62             eval 1+2 # 3
63             eval$ 3 # Same as above, but the return type is explicit
64             $ 3 # Probably same as above if $ alias is around
65             eval $^X # Possibly /usr/bin/perl
66             eval # Run current source-code line
67             eval? # but strips off leading 'if', 'while', ..
68             # from command
69             eval@ @ARGV # Make sure the result printed and saved as an array rather
70             # than as an array converted to a scalar.
71             @ @ARG # Same as above if @ alias is around
72             eval% %ENV # Make sure the result printed/saved as a hash
73             use English # Note this is a statement, not an expression
74             use English; # Same as above
75             eval$ use English # Error because this is not a valid expression
76              
77             =head2 See also:
78              
79             L<C<set auto
80             eval>|Devel::Trepan::CmdProcessor::Command::Set::Auto::Eval>,
81             L<C<set display eval>|Devel::Trepan::CmdProcessor::Command::Set::Display::Eval>, and
82             L<C<shell>|Devel::Trepan::CmdProcessor::Command::Shell>.
83             =cut
84             HELP
85              
86 12     12   87 no warnings 'redefine';
  12     1   27  
  12         5080  
  1         6  
  1         2  
  1         358  
87             sub complete($$)
88             {
89 0     0 0   my ($self, $prefix) = @_;
  0     0 0    
90 0 0         if (!$prefix) {
  0 0          
    0          
    0          
91 0 0         if (0 == index($self->{proc}{leading_str}, 'eval?')) {
  0 0          
92             Devel::Trepan::Util::extract_expression(
93 0           $self->{proc}->current_source_text());
  0            
94             } else {
95 0           $self->{proc}->current_source_text();
  0            
96             }
97             } elsif (substr($prefix, 0, 1) =~/[&A-Za-z_]/) {
98 0           Devel::Trepan::Complete::complete_subs($prefix);
  0            
99             } else {
100 0           ($prefix);
  0            
101             }
102             }
103              
104             sub run($$)
105             {
106 0     0 0   my ($self, $args) = @_;
  0     0 0    
107 0           my $proc = $self->{proc};
  0            
108 0           my $code_to_eval;
  0            
109 0           my $cmd_name = $args->[0];
  0            
110 0           my $eval_lead_word;
  0            
111 0           my $hide_position = 1;
  0            
112              
113 0 0         if (1 == scalar @$args) {
  0 0          
114 0 0         if ($proc->{terminated}) {
  0 0          
115 0           $proc->msg_need_running("implicit eval source code");
  0            
116 0           return;
  0            
117             }
118             # No string passed to eval. Pick up string to eval from
119             # current source text.
120 0           $code_to_eval = $proc->current_source_text();
  0            
121 0           $hide_position = 0;
  0            
122 0 0         if ('?' eq substr($cmd_name, -1)) {
  0 0          
123 0           $cmd_name = substr($cmd_name, 0, length($cmd_name)-1);
  0            
124 0           $code_to_eval =
  0            
125             Devel::Trepan::Util::extract_expression($code_to_eval);
126 0           $proc->msg("eval: ${code_to_eval}");
  0            
127 0           my @eval_args = split /\s+/, $code_to_eval;
  0            
128 0           $eval_lead_word = $eval_args[0];
  0            
129             } else {
130 0           my @eval_args = split /\s+/, $code_to_eval;
  0            
131 0           $eval_lead_word = $eval_args[0];
  0            
132             }
133             } else {
134             # Use cmd_argstr to ensure we do not try tokenize what was typed.
135             # But for purposes of sigil checking below, tokenization of the
136             # leading word is okay.
137 0           $code_to_eval = $proc->{cmd_argstr};
  0            
138 0           $eval_lead_word = $args->[1];
  0            
139             }
140             {
141 0           my $return_type = parse_eval_suffix($cmd_name);
  0            
  0            
  0            
142 0 0         $return_type = parse_eval_sigil($eval_lead_word) unless $return_type;
  0 0          
143 0           my $opts = {return_type => $return_type,
  0            
144             hide_position => $hide_position,
145             fix_file_and_line => 1,
146             };
147 12     12   96 no warnings 'once';
  12     1   29  
  12         1685  
  1         6  
  1         3  
  1         126  
148 0           $proc->eval($code_to_eval, $opts);
  0            
149             }
150             }
151              
152             unless (caller) {
153             require Devel::Trepan::CmdProcessor::Mock;
154             my $proc = Devel::Trepan::CmdProcessor::Mock::setup();
155             my $arg_str = '1 + 2';
156             $proc->{cmd_argstr} = $arg_str;
157             # print "eval ${arg_str} is: $cmd->run([$NAME, $arg_str])}\n";
158             $arg_str = 'return "foo"';
159             # # sub cmd.proc.current_source_text
160             # # {
161             # # 'return "foo"';
162             # # }
163             # $proc->{cmd_argstr} = $arg_str;
164             # print "eval? ${arg_str} is: ", $cmd->run([$NAME . '?'])";
165             }
166              
167             1;