# Copyright (c) 1997-2004
# Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany)
# http://www.math.tu-berlin.de/polymake, mailto:polymake@math.tu-berlin.de
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any
# later version: http://www.gnu.org/licenses/gpl.txt.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#----------------------------------------------------------------------------
# $Project: polymake $$Id: Property.pm 7470 2006-11-21 16:14:10Z gawrilow $
use strict;
use namespaces;
# for rulefile parser
package Poly::Property;
declare @decl_prologue;
@decl_prologue=split /(?<=\n)/, <<'_#_#_#_';
my ($type, $temporary, $diff, $accept, @upgrade, %apply_diff);
_#_#_#_
declare $decl_args='$type, $temporary && $Poly::Property::allow_temporary, $diff, $accept, @upgrade && \\@upgrade, \\%apply_diff';
declare $allow_temporary=1;
# Constructor
#
# new Poly::Property(Prototype, 'Name', $decl_args);
use Struct (
[ 'new' => '$$$;$$$$$' ],
[ '$name' => '#2' ], # 'property name'
[ '$belongs_to' => '#1' ], # Prototype
[ '$type' => '#3' ], #
'$dimension', # 0: scalar, 1: one line, all others: empty or multiple lines
'$allow_empty', # FIXME: unless each 'type' has a real constructor/verifier
[ '$temporary' => '#4' ], # boolean: get rid of the prop. value as soon as possible
# the following 3 fields contain \&sub or "method name",
# methods are called via the Poly::Object
[ '$diff' => '#5' ], # sub: old_data, new_data => diff or die('reason')
[ '$accept' => '#6' ], # sub: data => data or converted_data or die('reason')
'%apply_diff', # Property => sub: data, diff => converted_data
'@diff_sensitive', # ( Property ) having apply_diff{this property}
[ '@upgrade' => '#7' ], # ( version, \&sub, ... )
[ '$prod_method' => '"prod." . #2' ],
'@aliases', # alias names (currently kept here for solely documentation purposes)
);
# FIXME: idem
my %scalar_types=map { $_ => 1 }
qw(scalar boolean cardinal integer label word object);
my %numeric_types=map { $_ => 1 }
qw(scalar boolean cardinal integer);
my %container_types=map { $_=> 1 }
qw(vector array set list);
my %empty_container=map { $_=> 1 }
qw(vector array);
my $simple_container_re=qr{^ (\w+) <\s* (\w+) \s*> $ }x;
sub new {
my $self=&_new;
croak( "missing property type declaration\n" ) unless $self->type;
if (@_>6) {
my $apply_diff=pop @_;
while (my ($prop_name, $apply_diff_sub)=each %$apply_diff) {
my $prop=$self->belongs_to->lookup_property($prop_name)
or croak( "unknown property ", $self->belongs_to->name, "::$prop_name" );
croak( "property ", $prop->belongs_to->name, "::$prop_name does not have diff subroutine" )
unless defined $prop->diff;
push @{$prop->diff_sensitive}, $self;
$self->apply_diff->{$prop}=$apply_diff_sub;
}
}
$self->dimension= $scalar_types{$self->type} ? 0
: $container_types{$self->type} ? 1
: $self->type =~ $simple_container_re && $container_types{$1} && $scalar_types{$2} ? 1
: 2;
$self->allow_empty= $self->dimension>=2 ||
$self->dimension==1 &&
( $empty_container{$self->type} ||
$self->type =~ $simple_container_re && $empty_container{$1} );
$self;
}
1
syntax highlighted by Code2HTML, v. 0.9.1