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   94 use warnings; use utf8;
  12     12   30  
  12     1   386  
  12     1   150  
  12         25  
  12         88  
  1         7  
  1         3  
  1         20  
  1         5  
  1         1  
  1         6  
4 12     12   299 use rlib '../../../..';
  12     1   23  
  12         58  
  1         23  
  1         2  
  1         3  
5              
6             package Devel::Trepan::CmdProcessor::Command::Eval;
7 12     12   4659 use if !@ISA, Devel::Trepan::CmdProcessor::Command ;
  12     1   29  
  12         61  
  1         374  
  1         2  
  1         4  
8             unless (@ISA) {
9 12     12   73 eval <<'EOE';
  12     12   26  
  12     12   812  
  12     12   82  
  12     12   27  
  12     12   570  
  12         70  
  12         25  
  12         588  
  12         90  
  12         112  
  12         608  
  12         69  
  12         24  
  12         548  
  12         75  
  12         26  
  12         410  
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   1869 use strict;
  12     1   27  
  12         269  
  1         77  
  1         2  
  1         19  
19 12     12   66 use Devel::Trepan::Util;
  12     1   26  
  12         1530  
  1         4  
  1         2  
  1         122  
20              
21 12     12   89 use vars qw(@ISA); @ISA = @CMD_ISA;
  12     1   24  
  12         659  
  1         6  
  1         2  
  1         63  
22 12     12   74 use vars @CMD_VARS; # Value inherited from parent
  12     1   21  
  12         2005  
  1         6  
  1         1  
  1         122  
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   75 no warnings 'redefine';
  12     1   21  
  12         5434  
  1         6  
  1         2  
  1         394  
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   87 no warnings 'once';
  12     1   24  
  12         1825  
  1         7  
  1         2  
  1         125  
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;