Author: spadkins
Date: Fri Sep 7 06:02:15 2007
New Revision: 9921
Modified:
p5ee/trunk/App-Repository/lib/App/Repository.pm
p5ee/trunk/App-Repository/t/Repository-expr.t
Log:
enhance evaluate_constant_expression() to recognize functions (abs(a),
max(a,b), min(a,b))
Modified: p5ee/trunk/App-Repository/lib/App/Repository.pm
==============================================================================
--- p5ee/trunk/App-Repository/lib/App/Repository.pm (original)
+++ p5ee/trunk/App-Repository/lib/App/Repository.pm Fri Sep 7 06:02:15 2007
@@ -3455,26 +3455,81 @@
my ($self, $value) = @_;
my $NUM = '-?[0-9\.]+(?:[eE][+-]?[0-9]+)?';
- my ($val);
- while ($value =~ /\(([^()]*)\)/) {
- #print "EXPR: BEFORE $value\n";
- $val = $self->evaluate_constant_expression($1);
- $val = "undef" if (! defined $val);
- $value =~ s/\([^()]+\)/$val/;
- #print "EXPR: AFTER $value\n";
- }
- if ($value =~ m!^[-\+\*/0-9\.\s]+$!) { # all numeric expression
- $value =~ s/\s+//g;
- }
- while ($value =~ s~($NUM)\s*([\*/])\s*($NUM)~(!defined $1 || !defined $3)
? "undef" : (($2 eq "*") ? ($1 * $3) : (($3 && $3 != 0.0) ? ($1 / $3) :
"undef"))~e) {
- #print "EXPR: $1 $2 $3 = $value\n";
- # nothing else needed
- }
- while ($value =~ s~($NUM)\s*([\+-])\s*($NUM)~(!defined $1 || !defined $3)
? "undef" : (($2 eq "+") ? ($1 + $3) : ($1 - $3))~e) {
- #print "EXPR: $1 $2 $3 = $value\n";
- # nothing else needed
+ if (!defined $value || $value =~ /^$NUM$/) {
+ # do nothing
+ }
+ else {
+ my ($func, $found, $val, $val2, @vals);
+ while ($value =~ /([a-z_]+)\(([^()]*)\)/) {
+ #print "EXPR: BEFORE [$value] (func subst)\n";
+ $func = $1;
+ $found = $2;
+ $val = undef;
+ @vals = ();
+ foreach $val2 (split(/,/, $found)) {
+ push(@vals, $self->evaluate_constant_expression($val2));
+ }
+ if ($func eq "max") {
+ $val = undef;
+ foreach $val2 (@vals) {
+ if ($val2 =~ /^$NUM$/) {
+ if (! defined $val || $val2 > $val) {
+ $val = $val2;
+ }
+ }
+ else {
+ $val = undef;
+ last;
+ }
+ }
+ }
+ elsif ($func eq "min") {
+ $val = undef;
+ foreach $val2 (@vals) {
+ if ($val2 =~ /^$NUM$/) {
+ if (! defined $val || $val2 < $val) {
+ $val = $val2;
+ }
+ }
+ else {
+ $val = undef;
+ last;
+ }
+ }
+ }
+ elsif ($func eq "abs") {
+ if ($#vals == 0 && $vals[0] =~ /^$NUM$/) {
+ $val = $vals[0] < 0 ? -$vals[0] : $vals[0];
+ }
+ }
+ else { # unknown function name
+ $val = "undef";
+ }
+ $val = "undef" if (! defined $val);
+ $value =~ s/$func\([^\(\)]*\)/$val/;
+ #print "EXPR: AFTER [$value] (func subst)\n";
+ }
+ while ($value =~ /\(([^()]*)\)/) {
+ #print "EXPR: BEFORE $value\n";
+ $found = $1;
+ $val = $self->evaluate_constant_expression($found);
+ $val = "undef" if (! defined $val);
+ $value =~ s/\([^\(\)]*\)/$val/;
+ #print "EXPR: AFTER $value\n";
+ }
+ if ($value =~ m!^[-\+\*/0-9\.\s]+$!) { # all numeric expression
+ $value =~ s/\s+//g;
+ }
+ while ($value =~ s~($NUM)\s*([\*/])\s*($NUM)~(!defined $1 || !defined
$3) ? "undef" : (($2 eq "*") ? ($1 * $3) : (($3 && $3 != 0.0) ? ($1 / $3) :
"undef"))~e) {
+ #print "EXPR: $1 $2 $3 = $value\n";
+ # nothing else needed
+ }
+ while ($value =~ s~($NUM)\s*([\+-])\s*($NUM)~(!defined $1 || !defined
$3) ? "undef" : (($2 eq "+") ? ($1 + $3) : ($1 - $3))~e) {
+ #print "EXPR: $1 $2 $3 = $value\n";
+ # nothing else needed
+ }
+ $value = undef if ($value =~ /undef/);
}
- $value = undef if ($value =~ /undef/);
&App::sub_exit($value) if ($App::trace);
return($value);
Modified: p5ee/trunk/App-Repository/t/Repository-expr.t
==============================================================================
--- p5ee/trunk/App-Repository/t/Repository-expr.t (original)
+++ p5ee/trunk/App-Repository/t/Repository-expr.t Fri Sep 7 06:02:15 2007
@@ -11,6 +11,8 @@
use strict;
{
+ #$App::trace = 1;
+ #$App::trace = 1;
is(App::Repository->evaluate_constant_expression("1"), 1, "eval: 1");
is(App::Repository->evaluate_constant_expression("-1.5"), -1.5, "eval:
-1.5");
is(App::Repository->evaluate_constant_expression(" 2 "), 2, "eval: 2");
@@ -33,6 +35,13 @@
is(App::Repository->evaluate_constant_expression("1*2+3"), 5, "eval:
1*2+3");
is(App::Repository->evaluate_constant_expression("1*(2+3)"), 5, "eval:
1*(2+3)");
is(App::Repository->evaluate_constant_expression("((1-(2*3))+(12-5))*3"),
6, "eval: ((1-(2*3))+(12-5))*3");
+
is(App::Repository->evaluate_constant_expression("((1-(abs(-2*3)))+(max(12,2,3)-abs(5)))*3"),
6, "eval: ((1-(abs(-2*3)))+(max(12,2,3)-abs(5)))*3");
+ is(App::Repository->evaluate_constant_expression("(2/abs(-1))"), 2,
"(2/abs(-1))");
+ is(App::Repository->evaluate_constant_expression("abs(2/-1)"), 2,
"abs(2/-1)");
+ is(App::Repository->evaluate_constant_expression("max(-1,0,6,3)"), 6,
"eval: max(-1,0,6,3)");
+ is(App::Repository->evaluate_constant_expression("min(-1,0,6,3)"), -1,
"eval: min(-1,0,6,3)");
+ ok(App::Repository->evaluate_constant_expression("max(-1.3,-3e-1)") ==
-.3, "eval: max(-1.3,-3e-1)");
+ ok(App::Repository->evaluate_constant_expression("min(-1.3,-3e-1)") ==
-1.3, "eval: min(-1.3,-3e-1)");
my %values = (
x => 3,