# 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