Eobj
view release on metacpan or search on metacpan
Eobj/PLroot.pl view on Meta::CPAN
$self->const([@path, $_], @{$val});
} else {
$self->const([@path, $_], $val);
}
}
}
sub const {
my $self = shift;
my $prop = shift;
my @path = (ref($prop) eq 'ARRAY') ? @{$prop} : ($prop);
my @newval = @_;
my $pre = $self->getraw(@path);
if (defined($pre)) {
puke("Attempt to change a settable property into constant\n")
unless (ref($pre) eq 'PL_const');
my @pre = @{$pre};
my $areeq = ($#pre == $#newval);
my $i;
my $eq = $self->get(['plEQ',@path]);
if (ref($eq) eq 'CODE') {
for ($i=0; $i<=$#pre; $i++) {
$areeq = 0 unless (&{$eq}($pre[$i], $newval[$i]));
}
} else {
for ($i=0; $i<=$#pre; $i++) {
$areeq = 0 unless ($pre[$i] eq $newval[$i]);
}
}
unless ($areeq) {
if (($#path==2) && ($path[0] eq 'vars') && ($path[2] eq 'dim')) {
# This is dimension inconsintency. Will happen a lot to novices,
# and deserves a special error message.
wrong("Conflict in setting the size of variable \'$path[1]\' in ".
$self->who.". The conflicting values are ".
$self->prettyval(@pre)." and ".$self->prettyval(@newval).
". (This usually happens as a result of connecting variables of".
" different sizes, possibly indirectly)\n");
} else {
{ local $@; require Eobj::PLerrsys; } # XXX fix require to not clear $@?
my ($at, $hint) = &Eobj::PLerror::constdump();
wrong("Attempt to change constant value of \'".
join(",",@path)."\' to another unequal value ".
"on ".$self->who." $at\n".
"Previous value was ".$self->prettyval(@pre).
" and the new value is ".$self->prettyval(@newval)."\n$hint\n");
}
}
} else {
if ($Eobj::callbacksdepth) {
my $prop = join ",",@path;
my $who = $self->who;
hint("On $who: \'$prop\' = ".$self->prettyval(@newval)." due to magic property setting\n");
}
$self->domutate((bless \@newval, 'PL_const'), @path);
my $cbref = $self->getraw('plMAGICS', @path);
return unless (ref($cbref) eq 'PL_settable');
my $subref;
$Eobj::callbacksdepth++;
while (ref($subref=shift @{$cbref}) eq 'CODE') {
&{$subref}($self, @path);
}
$Eobj::callbacksdepth--;
}
}
sub set {
my $self = shift;
my $prop = shift;
my @path;
@path = (ref($prop) eq 'ARRAY') ? @{$prop} : ($prop);
my @newval = @_;
my $pre = $self->getraw(@path);
my $ppp = ref($pre);
puke ("Attempted to set a constant property\n")
if ((defined $pre) && ($ppp ne 'PL_settable'));
$self->domutate((bless \@newval, 'PL_settable'), @path);
return 1;
}
sub domutate {
my $self = shift;
my $newval = shift;
my $def = 0;
$def=1 if ((defined ${$newval}[0]) || ($#{$newval}>0));
if ($def) {
$self->{join("\n", 'plPROP', @_)} = $newval;
} else { delete $self->{join("\n", 'plPROP', @_)}; }
return 1;
}
sub seteq {
my $self = shift;
my $prop = shift;
my @path = (ref($prop) eq 'ARRAY') ? @{$prop} : ($prop);
my $eq = shift;
puke("Callbacks should be references to subroutines\n")
unless (ref($eq) eq 'CODE');
$self->set(['plEQ', @path], $eq);
}
sub addmagic {
my $self = shift;
my $prop = shift;
my @path = (ref($prop) eq 'ARRAY') ? @{$prop} : ($prop);
my $callback = shift;
unless (defined($self->get([@path]))) {
$self->punshift(['plMAGICS', @path], $callback);
} else {
$Eobj::callbacksdepth++;
&{$callback}($self, @path);
$Eobj::callbacksdepth--;
}
}
sub pshift {
my $self = shift;
my $prop = shift;
my @path = (ref($prop) eq 'ARRAY') ? @{$prop} : ($prop);
my $pre = $self->getraw(@path);
if (ref($pre) eq 'PL_settable') {
return shift @{$pre};
} else {
return $self->set($prop, undef) # We're changing a constant property here. Will puke.
if (defined $pre);
return undef; # There was nothing there.
}
}
sub ppop {
my $self = shift;
my $prop = shift;
my @path = (ref($prop) eq 'ARRAY') ? @{$prop} : ($prop);
my $pre = $self->getraw(@path);
if (ref($pre) eq 'PL_settable') {
return pop @{$pre};
} else {
return $self->set($prop, undef) # We're changing a constant property here. Will puke.
if (defined $pre);
return undef; # There was nothing there.
}
}
sub punshift {
my $self = shift;
my $prop = shift;
my @path = (ref($prop) eq 'ARRAY') ? @{$prop} : ($prop);
my @val = @_;
my $pre = $self->getraw(@path);
if (ref($pre) eq 'PL_settable') {
unshift @{$pre}, @val;
} else {
$self->set(\@path, (defined($pre))? ($pre, @val) : @val);
}
}
sub ppush {
my $self = shift;
my $prop = shift;
my @path = (ref($prop) eq 'ARRAY') ? @{$prop} : ($prop);
my @val = @_;
my $pre = $self->getraw(@path);
if (ref($pre) eq 'PL_settable') {
push @{$pre}, @val;
} else {
$self->set(\@path, (defined($pre))? (@val, $pre) : @val);
}
}
( run in 0.355 second using v1.01-cache-2.11-cpan-39bf76dae61 )