[system] / trunk / pg / lib / Parser / Constant.pm Repository:
ViewVC logotype

View of /trunk/pg/lib/Parser/Constant.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5509 - (download) (as text) (annotate)
Sat Sep 15 00:56:51 2007 UTC (12 years, 3 months ago) by dpvc
File size: 2603 byte(s)
Formula objects and Context objects contain reference loops, which
prevent them from being freed properly by perl when they are no longer
needed.  This is a source of an important memory leak in WeBWorK.  The
problem has been fixed by using Scalar::Util::weaken for these
recursive references, so these objects can be freed properly when they
go out of scope.  This should cause an improvement in the memory usage
of the httpd child processes.

    1 #########################################################################
    2 #
    3 #  Implements named constants (e, pi, etc.)
    4 #
    5 package Parser::Constant;
    6 use strict;
    7 our @ISA = qw(Parser::Item);
    8 
    9 $Parser::class->{Constant} = 'Parser::Constant';
   10 
   11 #
   12 #  If a constant is marked with isConstant, then it will
   13 #  be combined with other constants automatically as formulas
   14 #  are built, so only mark it if you want that to happen.
   15 #
   16 sub new {
   17   my $self = shift; my $class = ref($self) || $self;
   18   my $equation = shift;
   19   my ($name,$ref) = @_;
   20   my $const = $equation->{context}{constants}{$name};
   21   my ($value,$type) = Value::getValueType($equation,$const->{value});
   22   my $c = bless {
   23     name => $name, type => $type, def => $const,
   24     ref => $ref, equation => $equation
   25   }, $class;
   26   $c->weaken;
   27   $c->{isConstant} = 1 if $const->{isConstant};
   28   return $c;
   29 }
   30 
   31 #
   32 #  Return the value of the constant
   33 #    (for formulas, do the same substitutions the are in
   34 #     effect for the main equation).
   35 #
   36 sub eval {
   37   my $self = shift; my $context = $self->context;
   38   my $data = $self->{def}{value};
   39   if (Value::isFormula($data)) {
   40     $data = $data->copy;
   41     $data->{values} = $self->{equation}{values};
   42     $data = $data->{tree}->eval->inContext($context);
   43     return $data;
   44   } elsif (ref($data) eq 'ARRAY') {
   45     $data = [@${data}];
   46     foreach my $x (@{$data}) {$x = $x->copy->inContext($context)}
   47     return @{$data};
   48   } else {
   49     $data = $data->copy->inContext($context) if Value::isValue($data);
   50     return $data;
   51   }
   52 }
   53 
   54 #
   55 #  Use constant to tell if it can be in a union
   56 #
   57 sub canBeInUnion {
   58   my $self = shift;
   59   Value::isValue($self->{def}{value}) && $self->{def}{value}->canBeInUnion;
   60 }
   61 
   62 #
   63 #  Return the constant's name
   64 #
   65 sub string {
   66   my $self = shift;
   67   return $self->{def}{string} if defined($self->{def}{string});
   68   return $self->{name}
   69 }
   70 
   71 sub TeX {
   72   my $self = shift; my $name = $self->{name};
   73   return $self->{def}{TeX} if defined($self->{def}{TeX});
   74   $name = $1.'_{'.$2.'}' if ($name =~ m/^(\D+)(\d+)$/);
   75   return $name;
   76 }
   77 
   78 sub perl {
   79   my $self = shift; my $parens = shift;
   80   my $data = $self->{def}{value};
   81   return $self->{def}{perl} if defined($self->{def}{perl});
   82   if (Value::isFormula($data)) {
   83     $data->{values} = $self->{equation}{values};
   84     my $value = $data->{tree}->perl;
   85     $data->{values} = {};
   86     $value = '('.$value.')' if $parens;
   87     return $value;
   88   }
   89   $data = Value::makeValue($data,context=>$self->context);
   90   return $data->perl(@_) if Value::isValue($data);
   91   return '$'.$self->{name};
   92 }
   93 
   94 #########################################################################
   95 
   96 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9