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,

Reply via email to