1package Class::Contract;
2use strict;
3use vars qw( $VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS );
4require Exporter;
5use Carp;
6
7$VERSION = '1.14';
8
9@ISA = qw(Exporter);
10@EXPORT = qw(contract ctor dtor attr method pre impl post invar inherits
11             self value class abstract private optional check callstate
12             failmsg clon);
13@EXPORT_OK = qw(scalar_attrs array_attrs hash_attrs methods old);
14%EXPORT_TAGS = (DEFAULT  => \@EXPORT,
15                EXTENDED => \@EXPORT_OK,
16                ALL      => [@EXPORT, @EXPORT_OK]);
17
18my %contract;
19my %data;
20my %class_attr;
21my $current;
22my $msg_target;
23my %no_opt;    # NOT IN PRODUCTION
24# $Class::Contract::hook = \%data; # for testing GC # NOT IN PRODUCTION
25
26my @class_dtors;
27END { $_->()  foreach (@class_dtors) }
28
29my ($carp, $croak) = (
30  sub {
31    my (@c) = caller(0);
32    ($c[3] eq 'Class::Contract::__ANON__')
33      ? print STDERR (@_, " at $c[1] line $c[2]\n") : &carp
34  },
35  sub {
36    my (@c) = caller(0);
37    ($c[3] eq 'Class::Contract::__ANON__')
38      ? die(@_, " at $c[1] line $c[2]\n") : &croak
39  }
40);
41
42sub import {
43  my $class = $_[0];
44  my $caller = caller;
45  $contract{$caller}{use_old} = grep(/^old$/, @_) ? 1 : 0;
46  push @_, @EXPORT;
47  no strict 'refs';
48  INIT {
49    *{$caller .'::croak'} = $croak  if defined *{$caller .'::croak'}{'CODE'};
50    *{$caller .'::carp'}  = $carp   if defined *{$caller .'::carp'}{'CODE'};
51  }
52  goto &Exporter::import;
53}
54
55sub unimport {
56  my $class = shift;
57  my $caller = caller;
58  $contract{$caller}{use_old} = 0  if grep /^old$/, @_;
59}
60
61sub contract(&) {  $_[0]->();  _build_class(caller) }
62
63sub check(\%;$) {
64# NOT IN PRODUCTION...
65  my $state = !$#_ ? 0 : $_[1] ? 1 : 0;
66  defined $_
67    or croak("Usage:\n\tcheck \%sentinel",
68       ($#_ ? " => $state" : ""),
69       " for ( \@classes );\n\n");
70
71  my $forclass = $_;
72  $_[0]->{$forclass} =
73    bless { 'prev'     => $no_opt{$forclass},
74      'forclass' => $forclass }, 'Class::Contract::FormerState';
75  $no_opt{$forclass} = $state;
76# ...NOT IN PRODUCTION
77}
78
79# NOT IN PRODUCTION...
80sub Class::Contract::FormerState { # No function signature?
81  $no_opt{$_[0]->{'forclass'}} = $_[0]->{'prev'}; #  my ($self) = @_;
82}
83
84sub no_opt { # my ($class) = @_;
85  return   exists $no_opt{$_[0]}     ? $no_opt{$_[0]}
86         : exists $no_opt{'__ALL__'} ? $no_opt{'__ALL__'}
87         : 0;
88}
89# ...NOT IN PRODUCTION
90
91sub _location { # scalar context returns file and line of external code
92                # array context returns package aka 'owner', file and line
93  my ($i, @c, $owner);
94  while (@c = (caller($i++))[0..2]) {
95    if ($c[0] !~ /^Class::Contract$/) {
96      $owner = $c[0]  if !$owner;
97      if ($c[1] !~ /^\(eval \d+\)$/) {
98        return (wantarray ? $owner : (), join ' line ', @c[1,2]);
99      }
100    }
101  }
102}
103
104my %def_type = (
105  'attr'   => 'SCALAR',
106  'method' => '',
107  'ctor'   => '',
108  'dtor'   => '',
109  'clon'   => '',
110);
111
112sub _member {
113  my ($kind, $name, $type) = @_;
114  my ($owner, $location) = _location;
115  $name = ''  unless $name;
116
117  if (defined $contract{$owner}{$kind}{$name}) {
118    croak "\u$kind ${owner}::$name redefined"  if $name;
119    croak "Unnamed $kind redefined";
120  }
121
122  $contract{$owner}{$kind}{$name} = $current =
123    bless {'name'     => $name,
124           'type'     => $type || $def_type{$kind},
125           'gentype'  => $type || $def_type{$kind},  # NOT IN PRODUCTION
126           'loc'      => $location,
127           'shared'   => 0,
128           'private'  => 0,
129           'abstract' => 0,
130           'pre'      => [], # NOT IN PRODUCTION
131           'post'     => [], # NOT IN PRODUCTION
132          }, "Class::Contract::$kind";
133
134  # NOT IN PRODUCTION...
135  $current->{'gentype'} = 'OBJECT'
136    unless $current->{'gentype'} =~ /\A(SCALAR|ARRAY|HASH)\z/;
137  # ...NOT IN PRODUCTION
138  return $current;
139}
140
141sub attr($;$) { _member('attr'   => @_) }
142sub method($) { _member('method' => @_) }
143sub ctor(;$)  { _member('ctor'   => @_) }
144sub dtor()    { _member('dtor') }
145sub clon()    { _member('clone') }
146
147sub scalar_attrs(@) { map _member('attr', $_, 'SCALAR'), @_ }
148sub array_attrs(@)  { map _member('attr', $_, 'ARRAY'),  @_ }
149sub hash_attrs(@)   { map _member('attr', $_, 'HASH'),   @_ }
150sub methods(@)      { map _member('attr', $_),           @_ }
151
152sub class(@)    { $_->{'shared'}   = 1  foreach(@_); @_ }
153sub abstract(@) { $_->{'abstract'} = 1  foreach(@_); @_ }
154sub private(@)  { $_->{'private'}  = 1  foreach(@_); @_ }
155
156my %def_msg = (
157  'pre'   => 'Pre-condition at %s failed',
158  'post'  => 'Post-condition at %s failed',
159  'invar' => 'Class invariant at %s failed',
160  'impl'  => undef
161);
162
163sub _current {
164  my ($field, $code) = @_;
165  croak "Unattached $field"  unless defined $current;
166  croak "Attribute cannot have implementation"
167    if $current->isa('Class::Contract::attr') && $field eq 'impl';
168
169  my $descriptor = bless {
170    'code'  => $code,
171    'opt'   => 0,    # NOT IN PRODUCTION
172    'msg'   => $def_msg{$field},
173  }, 'Class::Contract::current';
174  @{$descriptor}{qw(owner loc)} = _location;
175
176  if ($field eq 'impl' && !( $current->isa('Class::Contract::ctor')
177                          || $current->isa('Class::Contract::dtor')
178                          || $current->isa('Class::Contract::clone') )) {
179    $current->{$field} = $descriptor
180  } else {
181    push @{$current->{$field}}, $descriptor
182  }
183
184  $msg_target = $descriptor;
185}
186
187sub failmsg {
188  croak "Unattached failmsg"  unless $msg_target;
189  $msg_target->{'msg'} = shift;
190}
191
192sub pre(&)  { _current('pre'  => @_) }
193sub post(&) { _current('post' => @_) }
194sub impl(&) { _current('impl' => @_) }
195
196sub optional { # my (@descriptors) = @_;
197  $_->{'opt'} = 1  foreach(@_); @_ # NOT IN PRODUCTION
198}
199
200sub invar(&) {
201  my ($code) = @_;
202
203  my $descriptor = {
204    'code'  => $code,
205    'opt'   => 0,    # NOT IN PRODUCTION
206    'msg'   => $def_msg{'invar'},
207  };
208  @{$descriptor}{qw(owner loc)} = _location;
209
210  push @{$contract{$descriptor->{'owner'}}{'invar'}}, $descriptor;
211  $msg_target = $descriptor;
212}
213
214
215sub inherits(@)  {
216  my ($owner) = _location;
217  foreach (@_) {
218    croak "Can't create circular reference in inheritence\n$_ is a(n) $owner"
219      if $_->isa($owner)
220  }
221  push @{$contract{$owner}{'parents'}}, @_;
222}
223
224sub _build_class($) {
225  my ($class) = @_;
226  my $spec = $contract{$class};
227  _inheritance($class, $spec);
228  _attributes($class, $spec);
229  _methods($class, $spec);
230  _constructors($class, $spec);
231  _destructors($class, $spec);
232  _clones($class, $spec);
233  1;
234}
235
236localscope: {
237  my @context;
238  my %clear; # NOT IN PRODUCTION;
239  sub _set_context  {
240    push @context, {'__SELF__' => shift};
241
242    # NOT IN PRODUCTION...
243    my $proto = $context[-1]{__SELF__};
244    my ($class, $obj) = ref($proto)
245      ? (ref($proto), $proto)
246      : ($proto, undef);
247    return  if $class =~ /^Class::Contract::Old::_/;
248
249    if ($contract{$class}{'use_old'}) {
250      my $class_old = "Class::Contract::Old::_$#context";
251      _pkg_copy($class, $class_old);
252      my $old = $class_old;
253      if ($obj) {
254        # Like generic_clone but into the cloned class
255        my $old_key = \ my $undef;
256        $old = bless \ $old_key, $class_old;
257        $data{$$old} = _dcopy($data{$$obj})  if exists $data{$$obj};
258      }
259      $context[-1]{__OLD__} = $old;
260    }
261    # ...NOT IN PRODUCTION
262  }
263  sub _free_context {
264    return pop @context
265  }
266  sub old() {
267    croak "No context. Can't call &old"  unless @context;
268    my $self = $context[-1]{__SELF__};
269    my $class = ref($self) || $self;
270    croak "Support for &old has been toggled off"
271      unless ($contract{$class}{'use_old'});
272    $context[-1]{__OLD__} # NOT IN PRODUCTION
273  }
274
275  my @value;
276  sub _set_value  { push @value, \@_ }
277  sub _free_value { my $v = pop @value; wantarray ? @$v : $v->[0] }
278
279  sub value {
280    croak "Can't call &value "  unless @value;
281    return $value[-1];
282  }
283
284  sub self() {
285    if (@_) {
286      # NOT IN PRODUCTION...
287      croak "Usage:\tself(\$class_or_object)"
288        unless defined *{join(ref($_[0])||$_[0], '::')};
289      # ...NOT IN PRODUCTION
290      $context[-1]{__SELF__} = shift;
291    }
292    croak "No context. Can't call &self"  unless @context;
293    $context[-1]{__SELF__}
294  }
295
296  sub callstate() {
297    croak "No context. Can't call &callstate"  unless @context;
298    return $context[-1];
299  }
300}
301
302sub _inheritance {                                  #  A  D  Invokation order
303# Inheritence is left-most depth-first. Destructors #  /\ |
304# are called in reversed order as the constructors  # B C E    ctor: ABCDEF
305# Diamond patterns in inheritence are 'handled' by  #  \//     dtor: FEDCBA
306# looking for and skipping duplicate anonymous refs #   F
307
308  my ($classname, $spec) = @_;
309  my (%inherited_clause, %inherited_impl);
310  foreach my $ancestor ( reverse @{$spec->{'parents'} || [] } ) {
311    my $parent = $contract{$ancestor} || next;
312    if ($parent->{'use_old'} and not $spec->{'use_old'}) {
313      croak("Derived class $classname, has not toggled on support for ->old\n",
314            "which is required by ancestor $ancestor. Did you forget to\n",
315            "declare: use Class::Contract 'old'; ?");
316    }
317    foreach my $clause ( qw( attr method ctor clone dtor ) ) {
318      foreach my $name ( keys %{ $parent->{$clause} || {} } ) {
319        # Inherit each clause from ancestor unless defined
320        if (! defined $spec->{$clause}{$name}
321            and not exists $inherited_clause{$name}) {
322          $inherited_clause{$name}++;
323          %{$spec->{$clause}{$name}} = (%{$parent->{$clause}{$name}});
324          $spec->{$clause}{$name}{'pre'}  = []; # NOT IN PRODUCTION
325          next;
326        }
327
328        # Inherit ctor/clone/dtor invokation from ancestors
329        if ($clause =~ /^(ctor|clone|dtor)$/) {
330          if (defined $parent->{$clause}{$name}{'impl'}
331              and @{$parent->{$clause}{$name}{'impl'}}) {
332            my (@impl, %seen) = (@{$spec->{$clause}{$name}{'impl'}});
333            if (@impl) {
334              $seen{$impl[$_]} = $_  foreach (0..$#impl);
335              foreach my $item ( @{$parent->{$clause}{$name}{'impl'}} ) {
336                splice(@{$spec->{$clause}{$name}{'impl'}}, $seen{$item}, 1)
337                   if exists $seen{$item};
338              }
339            }
340            $clause ne 'dtor'
341            ? unshift(@{$spec->{$clause}{$name}{'impl'}},
342                      @{$parent->{$clause}{$name}{'impl'}})
343            : push(@{$spec->{$clause}{$name}{'impl'}},
344                   @{$parent->{$clause}{$name}{'impl'}});
345          }
346        }
347
348        # Get implementation from ancestor if derived but not redefined
349        if ($clause eq 'method') {
350          if (! defined $spec->{$clause}{$name}{'impl'}
351              or $inherited_impl{$name}) {
352            $inherited_impl{$name}++;
353            $spec->{$clause}{$name}{'impl'}=$parent->{$clause}{$name}{'impl'};
354          }
355          croak("Forget 'private'? $classname inherits private $name from ",
356                "$ancestor\n")
357            if ($parent->{$clause}{$name}{'private'}
358                and not $spec->{$clause}{$name}{'private'})
359        }
360        # NOT IN PRODUCTION...
361        # Inherit all post-conditions from ancestors
362        if (@{$parent->{$clause}{$name}{'post'}||[]}) {
363          my (@post, %seen) = (@{$spec->{$clause}{$name}{'post'}});
364          if (@post) {
365            $seen{$post[$_]} = $_  foreach (0..$#post);
366            foreach my $item ( @{$parent->{$clause}{$name}{'post'}} ) {
367              splice(@{$spec->{$clause}{$name}{'post'}}, $seen{$item}, 1)
368                if exists $seen{$item};
369            }
370          }
371          push(@{$spec->{$clause}{$name}{'post'}},
372               @{$parent->{$clause}{$name}{'post'}});
373        }
374        # ...NOT IN PRODUCTION
375      }
376    }
377    # NOT IN PRODUCTION...
378    # Inherit all class invariants from ancestors
379    if (defined $parent->{'invar'} and @{$parent->{'invar'}}) {
380      defined $spec->{'invar'} or $spec->{'invar'} = [];
381      my (@invar, %seen) = (@{$spec->{'invar'}});
382      if (@invar) {
383        $seen{$invar[$_]} = $_  foreach (0..$#invar);
384        foreach (@{$parent->{'invar'}}) {
385          splice(@{$spec->{'invar'}}, $seen{$_}, 1)  if exists $seen{$_}
386        }
387      }
388      push @{$spec->{'invar'}}, @{$parent->{'invar'}};
389    }
390    # ...NOT IN PRODUCTION
391  }
392
393  no strict 'refs';
394  unshift @{"${classname}::ISA"}, @{ $spec->{'parents'} || [] };
395}
396
397sub _attributes {
398  my ($classname, $spec) = @_;
399
400  while ( my ($name, $attr) = each %{$spec->{'attr'}} ) {
401    if ($attr->{'shared'}) {
402      my $ref = $class_attr{$classname}{$name} =
403        $attr->{'type'} eq 'ARRAY'  ? []
404      : $attr->{'type'} eq 'HASH'   ? {}
405      : $attr->{'type'} eq 'SCALAR' ? do { \ my $scalar }
406      : eval { $attr->{'type'}->new }
407        || croak "Unable to create $attr->{'type'} object ",
408                 "for class attribute $name";
409    }
410
411    localscope: {
412      no strict 'refs';
413      local $^W;
414      *{"${classname}::$name"} = sub {
415        croak(qq|Can\'t access object attr w/ class reference |,$attr->{'loc'})
416          unless ($attr->{'shared'} or ref($_[0]));
417
418        my $caller = caller;
419        croak "attribute ${classname}::$name inaccessible from package $caller"
420          unless $classname->isa($caller);
421
422        my $self = shift;
423        _set_context(($attr->{'shared'} ? ref($self)||$self : $self),
424                     join ' line ', [caller]->[1,2]);
425        my $attr_ref = ($attr->{'shared'})
426          ? $class_attr{$classname}{$name}
427          : $data{$$self}{$name};
428        _set_value $attr_ref;
429
430        # NOT IN PRODUCTION...
431        my @fail = generic_check('pre', 'attr' => $name, $spec);
432        croak @fail  if @fail;
433        # ...NOT IN PRODUCTION
434
435        _free_context;
436
437        # NOT IN PRODUCTION...
438        return "Class::Contract::Post$attr->{'gentype'}"->new(
439          $attr->{'post'}, $attr_ref, $name,
440        )  if @{$attr->{'post'}};
441        # ...NOT IN PRODUCTION
442
443        scalar _free_value;
444        return $attr_ref;
445      };
446    }
447  }
448}
449
450sub _methods {
451  my ($classname, $spec) = @_;
452
453  while ( my ($name, $method) = each %{$spec->{'method'}} ) {
454    $spec->{'abstract'} ||= $method->{'abstract'};
455    unless ($method->{'impl'}) {
456      if ($method->{'abstract'}) {
457        $method->{'impl'} = {'code' => sub {
458          croak "Can't call abstract method ${classname}::$name"
459        } }
460      } else {
461        croak qq{No implementation for method $name at $method->{'loc'}.\n},
462        qq{(Did you forget to declare it 'abstract'?)\n}
463      }
464    }
465
466    local_scope: {
467      local $^W;
468      no strict 'refs';
469      *{"${classname}::$name"} = sub {
470        my $caller = caller;
471        croak("private method ${classname}::$name inaccessible from ",
472              scalar caller)
473          if ($method->{'private'}
474              and not ($classname->isa($caller))); # or $caller->isa($classname)));
475
476        my $self = shift;
477        _set_context(($method->{'shared'} ? ref($self)||$self : $self),
478                     join ' line ', [caller]->[1,2]);
479
480        # NOT IN PRODUCTION...
481        croak(qq|Can\'t invoke object method w/ class name |, $method->{'loc'})
482          unless ($method->{'shared'} or ref($self));
483
484        my $no_opt = no_opt($classname);
485        my @fail = generic_check('pre', 'method' => $name, $spec, @_);
486        croak @fail  if @fail;
487        # ...NOT IN PRODUCTION
488
489        _set_value wantarray
490          ? $method->{'impl'}{'code'}->(@_)
491          : scalar $method->{'impl'}{'code'}->(@_);
492
493        # NOT IN PRODUCTION...
494        generic_check('post',  'method' => $name, $spec, @_);
495        generic_check('invar', 'method' => $name, $spec, @_)
496          if (caller ne $classname);
497        # ...NOT IN PRODUCTION
498
499        _free_context;
500        _free_value;
501      };
502    }
503  }
504}
505
506# NOT IN PRODUCTION...
507sub generic_check {
508  return  if (ref(self)||self) =~ /^Class::Contract::Old::_/;
509
510  my ($type, $kind, $name, $class_spec, @args) = @_;
511  my @specs = @{$class_spec->{$kind}{$name}{$type}||[]};
512  my @errors;
513
514  foreach my $spec ( @specs ) {
515    next  if $spec->{'opt'} && no_opt($spec->{'owner'})
516      || $spec->{'code'}->(@args);
517    push @errors, sprintf($spec->{'msg'},$spec->{'loc'})."\n";
518  }
519
520  @errors ? croak @errors : return   unless $type eq 'pre';
521  return  if @specs && !@errors;
522
523  # OTHERWISE SATISFY AT LEAST ONE PARENT?
524  foreach my $ancestor ( @{$class_spec->{'parents'}||[]} ) {
525    my $parent = $contract{$ancestor};
526    next  unless exists $parent->{$kind}{$name};
527    my $has_pre = scalar @{$parent->{$kind}{$name}{'pre'}};
528    unless ($has_pre) {
529      foreach my $p (@{$parent->{'parents'}||[]}) {
530        $has_pre++ and last  if _hasa($p, $kind, $name, 'pre');
531      }
532    }
533
534    if ($has_pre) {
535      my @par_err = generic_check($type, $kind, $name, $parent, @args);
536      return  unless @par_err;
537      push @errors, @par_err;
538    }
539  }
540  return @errors;
541}
542
543sub _hasa {
544  my ($class, $kind, $name, $type) = (@_);
545  return 0  unless defined $contract{$class}{$kind}{$name};
546
547  my $has = @{$contract{$class}{$kind}{$name}{$type} || []} ? 1 : 0;
548  unless ($has) {
549    foreach my $ancestor (@{$contract{$class}{'parents'} || []}) {
550      $has++ and last  if _hasa($ancestor, $kind, $name, $type);
551    }
552  }
553  return $has;
554}
555# ...NOT IN PRODUCTION
556
557sub generic_ctor {
558  my ($class) = @_;
559
560  croak "Class $class has abstract methods. Can't create $class object"
561    if $contract{$class}{'abstract'};
562
563  my $key = \ my $undef;
564  my $obj = \ $key;
565  bless $obj, $class;
566
567  my $attr = $contract{$class}{'attr'};
568
569  foreach my $attrname ( keys %$attr ) {
570    unless ($attr->{$attrname} && $attr->{$attrname}{'shared'}) {
571      my $ref = $data{$key}{$attrname}
572      = $attr->{$attrname}{'type'} eq 'ARRAY'  ? []
573      : $attr->{$attrname}{'type'} eq 'HASH'   ? {}
574      : $attr->{$attrname}{'type'} eq 'SCALAR' ? do { \my $scalar }
575      : eval { $attr->{$attrname}{type}->new }
576      || croak "Unable to create $attr->{$attrname}{'type'} ",
577               "object for attribute $attrname";
578    }
579  }
580
581  return $obj;
582}
583
584sub generic_clone ($) {
585  my $self = shift;
586  my $ref = ref($self);
587  croak "usage: \$object->clone -Invalid arg $self"
588    unless ($ref and
589            $ref !~ /^(HASH|ARRAY|SCALAR|GLOB|FORMAT|CODE|Regexp|REF)$/);
590  my $key  = \ my $undef;
591  my $obj  = bless \$key, $ref;
592  $data{$key} = _dcopy($data{$$self})  if exists $data{$$self};
593  return $obj;
594}
595
596
597sub _constructors {
598  my ($classname, $spec) = @_;
599  my $noctor = 1;
600
601  while ( my ($name, $ctor) = each %{$spec->{'ctor'}} ) {
602    $noctor &&= $ctor->{'shared'}
603  }
604
605  $spec->{'ctor'}{'new'} = bless {
606    'name'     => 'new',
607    'shared'   => 0,
608    'abstract' => 0,
609    'loc'      => '<implicit>'
610  }, 'Class::Contract::ctor'
611    if $noctor;
612
613  while ( my ($name, $ctor) = each %{$spec->{'ctor'}} ) {
614    $spec->{'abstract'} ||= $ctor->{'abstract'};
615
616    if ($ctor->{'shared'}) {
617      localscope: {
618        local $^W;
619        no strict 'refs';
620        my $classctor = sub {
621          my $self = shift;
622          _set_context ref($self)||$self;
623
624          # NOT IN PRODUCTION...
625          my @fail = generic_check('pre', 'ctor' => $name, $spec, @_);
626          croak @fail  if @fail;
627          # ...NOT IN PRODUCTION
628
629          $_->{'code'}->(@_)  foreach ( @{$ctor->{'impl'}} );
630
631          # NOT IN PRODUCTION...
632          generic_check('post', 'ctor' => $name, $spec, @_);
633          generic_check('invar','ctor' => $name, $spec, @_)
634            if (caller ne $classname);
635          # ...NOT IN PRODUCTION
636
637          _free_context;
638        };
639        $classname->$classctor();
640#        *{"${classname}::$name"} = $classctor  if $name;
641      }
642    } else {
643      localscope:{
644        local $^W;
645        no strict 'refs';
646        *{"${classname}::$name"} = sub {
647          my $proto = shift;
648          my $class = ref($proto)||$proto;
649          my $self = Class::Contract::generic_ctor($class);
650          _set_context $self;
651
652          # NOT IN PRODUCTION...
653          my @fail = generic_check('pre', 'ctor' => $name, $spec, @_);
654          croak @fail  if @fail;
655          # ...NOT IN PRODUCTION
656
657          $_->{'code'}->(@_)  foreach ( @{$ctor->{'impl'}} );
658
659          # NOT IN PRODUCTION...
660          generic_check('post', 'ctor' => $name, $spec, @_);
661          generic_check('invar','ctor' => $name, $spec, @_)
662            if (caller ne $classname);
663          # ...NOT IN PRODUCTION
664
665          _free_context;
666          return $self;
667        }
668      }
669    }
670  }
671}
672
673use Data::Dumper;
674sub _destructors {
675
676  my ($classname, $spec) = @_;
677  my $dtorcount = 0;
678
679  while ( my ($name, $dtor) = each %{$spec->{'dtor'}} ) {
680    $spec->{'abstract'} ||= $dtor->{'abstract'};
681
682    if ($dtor->{'shared'}) {
683      localscope: {
684        local $^W;
685        no strict 'refs';
686        my $classdtor = sub {
687          croak "Illegal explicit invokation of class dtor", $dtor->{'loc'}
688            if caller() ne 'Class::Contract';
689          my $self = shift;
690          $self = ref $self  if ref $self;
691
692          _set_context $self;
693
694          # NOT IN PRODUCTION...
695          my @fail = generic_check('pre', 'dtor' => $name, $spec, @_);
696          croak @fail  if @fail;
697          # ...NOT IN PRODUCTION
698
699          $_->{'code'}->(@_)  foreach ( @{$dtor->{'impl'}} );
700
701          generic_check('post', 'dtor' => $name, $spec, @_);# NOT IN PRODUCTION
702          _free_context;
703        };
704
705        push @class_dtors, sub { $classname->$classdtor() };
706      }
707    } else {
708      croak "Class $classname has too many destructors"  if $dtorcount++;
709
710      localscope: {
711        local $^W;
712        no strict 'refs';
713        my $objdtor = sub {
714          croak "Illegal explicit invokation of object dtor", $dtor->{'loc'}
715            if caller() ne 'Class::Contract';
716
717          my $self = shift;
718          _set_context $self;
719
720          # NOT IN PRODUCTION...
721          my @fail = generic_check('pre', 'dtor' => $name, $spec, @_);
722          croak @fail  if @fail;
723          # ...NOT IN PRODUCTION
724
725          $_->{'code'}->(@_)  foreach ( @{$dtor->{'impl'}||[]} );
726
727          # NOT IN PRODUCTION...
728          generic_check('post',  'dtor' => $name, $spec, @{[@_]});
729          generic_check('invar', 'dtor' => $name, $spec, @{[@_]})
730            if (caller ne $classname);
731          # ...NOT IN PRODUCTION
732
733          _free_context;
734          return;
735        };
736
737        *{"${classname}::DESTROY"} = sub {
738          $_[0]->$objdtor();
739          delete $data{${$_[0]}}  if exists $data{${$_[0]}};
740        };
741      }
742    }
743  }
744  unless (defined &{"${classname}::DESTROY"}) {
745    local $^W;
746    no strict 'refs';
747    *{"${classname}::DESTROY"} = sub {
748      delete $data{${$_[0]}}  if exists $data{${$_[0]}};
749    };
750  }
751}
752
753sub _clones {
754  my ($classname, $spec) = @_;
755  my $clone_count = 0;
756
757  $spec->{'clone'}{''} = bless {
758    'name'     => '',
759    'shared'   => 0,
760    'abstract' => 0,
761    'loc'      => '<implicit>'
762  }, 'Class::Contract::clone'
763    unless $spec->{'clone'};
764
765  while ( my ($name, $clause) = each %{$spec->{'clone'}} ) {
766
767    $spec->{'abstract'} ||= $clause->{'abstract'};
768    croak "'class' clause can not be used to qualify 'clon'"
769      if $clause->{'shared'};
770    croak "too many clon clauses"  if $clone_count++;
771
772    localscope: {
773      local $^W;
774      no strict 'refs';
775      *{"${classname}::clone"} = sub {
776        my $self = shift;
777        $self = generic_clone($self);
778        _set_context $self;
779
780        # NOT IN PRODUCTION...
781        my @fail = generic_check('pre', 'dtor' => $name, $spec, @_);
782        croak @fail  if @fail;
783        # ...NOT IN PRODUCTION
784
785        $_->{'code'}->(@_)  foreach ( @{$clause->{'impl'}||[]} );
786
787        # NOT IN PRODUCTION...
788        generic_check('post',  $clause => $name, $spec, @{[@_]});
789        generic_check('invar', $clause => $name, $spec, @{[@_]})
790          if (caller ne $classname);
791        # ...NOT IN PRODUCTION
792
793        _free_context;
794        return $self;
795      };
796    }
797  }
798}
799
800localscope: {
801  my ($a,$z) = (qr/(^|^.*?=)/, qr/\(.*?\)$/);
802  my %seen = ();
803  my $depth = 0;
804  sub _dcopy { # Dereference and return a deep copy of whatever's passed
805    my ($r, $ref, $rval);
806    $ref = ref($_[0])   or return $_[0];
807    exists $seen{$_[0]} and return $seen{$_[0]};
808    $depth++;
809
810    $r =
811      ($_[0] =~ /${a}HASH$z/)   ? {map _dcopy($_), (%{$_[0]})}
812    : ($_[0] =~ /${a}ARRAY$z/)  ? [map _dcopy($_), @{$_[0]} ]
813    : ($_[0] =~ /${a}SCALAR$z/) ? do { my $v = _dcopy(${$_[0]}); \$v }
814    : ($_[0] =~ /${a}FORMAT$z/) ? $_[0]
815    : ($_[0] =~ /${a}CODE$z/)   ? $_[0]
816    : ($_[0] =~ /${a}Regexp$z/) ? $_[0]
817    : ($_[0] =~ /${a}REF$z/)    ? $_[0]
818    : ($_[0] =~ /${a}GLOB$z/)   ? $_[0]
819    : $_[0]->can('clone') ? $_[0]->clone : $_[0];
820
821    $rval = $ref =~ /^(HASH|ARRAY|SCALAR|GLOB|FORMAT|CODE|Regexp|REF)$/
822             ? $r
823             : bless $r, $ref;
824
825    --$depth
826      and $seen{$_[0]} = $rval
827      or  %seen = ();
828
829    return $rval;
830  }
831}
832
833# NOT IN PRODUCTION...
834sub _pkg_copy ($$) { # $from_package, $to_package
835  no strict 'refs';
836  defined *{$_[0] . '::'}
837    or croak "_pkg_copy() Can't clone from non-existant package $_[0]";
838  defined *{$_[1] . '::'} and *{$_[1] . '::'} = {};
839
840  foreach my $glob (values %{*{$_[0] . '::'}}) {
841    my ($varname) = $glob =~ /^\*$_[0]::(.*)/ or next;
842    foreach my $slot (qw(SCALAR ARRAY HASH CODE FORMAT)) {
843      my $ref = _dcopy(*{"$_[0]::$varname"}{$slot});
844      *{"$_[1]::$varname"} = $ref  if defined $ref;
845    }
846  }
847}
848
849sub _pkg_clear ($) {
850  no strict 'refs';
851  my ($package) = shift;
852  my $stash = *{$package . '::'}{HASH};
853  foreach my $name (keys %$stash) {
854    $name = join('::', $package, $name);
855#    print "undef $name\n";
856    undef $$name;
857    undef @$name;
858    undef %$name;
859
860    undef &$name;
861    undef *$name;
862  }
863  undef %{$package . '::'};
864}
865
866sub Class::Contract::PostOBJECT::new {
867  my ($class, $posts, $original, $name) = @_;
868  my $objclass = ref $original;
869  carp("Warning: cannot check post-condition",
870       (@$posts==1?"":'s'),
871       " on $objclass attribute '$name'")
872    if $^W;
873  _free_value;
874  return $original;
875}
876
877package Class::Contract::PostSCALAR;
878
879sub new {
880  my $proxy;
881  tie $proxy, 'Class::Contract::PostSCALAR', @_;
882  return \$proxy;
883}
884
885sub TIESCALAR {
886  my ($class, $self, $postsubs, $original) = @_;
887  return bless {
888    'orig' => $original,
889    'post' => $postsubs,
890  }, $class;
891}
892
893sub FETCH { return ${$_[0]->{'orig'}} }
894sub STORE { ${$_[0]->{'orig'}} = $_[1] }
895
896sub DESTROY {
897  Class::Contract::generic_check('post', 'attr', @{self()}{qw(orig spec)}, @_);
898  Class::Contract::_free_value();
899}
900
901package Class::Contract::PostARRAY;
902
903sub new {
904  my @proxy;
905  tie @proxy, 'Class::Contract::PostARRAY', @_;
906  if ($_[3]) { bless \@proxy, ref $_[2] }
907  return \@proxy;
908}
909
910sub TIEARRAY {
911  my ($class, $self, $postsubs, $original) = @_;
912  return bless { 'orig' => $original,
913     'post' => $postsubs,
914         }, $class;
915}
916
917sub FETCH       { $_[0]->{'orig'}->[$_[1]] }
918sub FETCHSIZE   { scalar @{$_[0]->{'orig'}} }
919sub STORE       { $_[0]->{'orig'}->[$_[1]] = $_[2] }
920sub STORESIZE   { $#{$_[0]->{'orig'}} = $_[1]-1 }
921sub EXTEND      { $#{$_[0]->{'orig'}} = $_[1]-1 }
922sub CLEAR       { @{$_[0]->{'orig'}} = () }
923sub PUSH        { push @{$_[0]->{'orig'}}, @_[1..$#_] }
924sub POP         { pop @{$_[0]->{'orig'}} }
925sub UNSHIFT     { unshift @{$_[0]->{'orig'}}, @_[1..$#_] }
926sub SHIFT       { shift @{$_[0]->{'orig'}} }
927
928sub DESTROY {
929  Class::Contract::generic_check('post', 'attr', @{self()}{qw(orig spec)}, @_);
930  Class::Contract::_free_value();
931}
932
933
934package Class::Contract::PostHASH;
935
936sub new {
937  my %proxy;
938  tie %proxy, 'Class::Contract::PostHASH', @_;
939  if ($_[3]) { bless \%proxy, ref $_[2] }
940  return \%proxy;
941}
942
943sub TIEHASH {
944  my ($class, $self, $postsubs, $original) = @_;
945  return bless { 'orig' => $original,
946     'post' => $postsubs,
947         }, $class;
948}
949
950sub FETCH       { $_[0]->{'orig'}->{$_[1]} }
951sub STORE       { $_[0]->{'orig'}->{$_[1]} = $_[2] }
952sub EXISTS      { exists $_[0]->{'orig'}->{$_[1]} }
953sub DELETE      { delete $_[0]->{'orig'}->{$_[1]} }
954sub CLEAR       { %{$_[0]->{'orig'}} = () }
955sub FIRSTKEY    { keys %{$_[0]->{'orig'}}; each %{$_[0]->{'orig'}} }
956sub NEXTKEY     { each %{$_[0]->{'orig'}} }
957
958sub DESTROY {
959  Class::Contract::generic_check('post', 'attr', @{self()}{qw(orig spec)}, @_);
960  Class::Contract::_free_value();
961}
962# ...NOT IN PRODUCTION
963
9641;
965
966__END__
967
968=head1 NAME
969
970Class::Contract - Design-by-Contract OO in Perl.
971
972=head1 VERSION
973
974This document describes version 1.10 of Class::Contract,
975released February  9, 2001.
976
977=head1 SYNOPSIS
978
979    package ClassName
980    use Class::Contract;
981
982    contract {
983      inherits 'BaseClass';
984
985      invar { ... };
986
987      attr 'data1';
988      attr 'data2' => HASH;
989
990      class attr 'shared' => SCALAR;
991
992      ctor 'new';
993
994      method 'methodname';
995        pre  { ... };
996          failmsg 'Error message';
997
998        post  { ... };
999          failmsg 'Error message';
1000
1001        impl { ... };
1002
1003      method 'nextmethod';
1004        impl { ... };
1005
1006      class method 'sharedmeth';
1007        impl { ... };
1008
1009      # etc.
1010    };
1011
1012
1013=head1 DESCRIPTION
1014
1015=head2 Background
1016
1017Design-by-contract is a software engineering technique in which each
1018module of a software system specifies explicitly what input (or data or
1019arguments) it requires, and what output (or information or results) it
1020guarantees to produce in response.
1021
1022These specifications form the "clauses" of a contract between a
1023module and the client software that uses it. If the client software
1024abides by the input requirements, the module guarantees to produce
1025the correct output. Hence by verifying these clauses at each
1026interaction with a module, the overall behaviour of the system can
1027be confidently predicted.
1028
1029Design-by-contract reinforces the benefits of modular design techniques
1030by inserting explicit compile-time or run-time checks on a contract.
1031These checks are most often found in object-oriented languages
1032and are typically implemented as pre-conditions and post-conditions
1033on methods, and invariants on classes.
1034
1035Note that these features differ from simple verification statements
1036such as the C C<assert> statement. Conditions and invariants are
1037properties of a class, and are inherited by derived classes.
1038
1039An additional capacity that is often provided in design-by-contract
1040systems is the ability to selectively disable checking in production
1041code. This allows the contractual testing to be carried out
1042during implementation, without impinging on the performance of
1043the final system.
1044
1045=head2 Adding design-by-contract to Perl
1046
1047The Class::Contract module provides a framework for specifying
1048methods and attributes for a class (much like the existing class
1049definition modules Class::Struct, Class::MethodMaker, and
1050Class::Generate). Class::Contract allows both per-object and per-class
1051methods and attributes to be defined. Attributes may be scalar-, array-,
1052hash-, or object-based.
1053
1054Class::Contract differs from other class-specification modules (except
1055Class::Generate) in that it also provides the ability to specify
1056invariant conditions on classes, and pre- and post-conditions on methods
1057and attributes. All of these clauses are fully inheritable, and may be
1058selectively disabled. It differs from all other modules in that it has a
1059cleaner, simpler specification syntax, and -- more importantly -- it
1060enforces encapsulation of object attributes, thereby ensuring that the
1061class contract cannot be subverted.
1062
1063
1064=head2 Defining classes
1065
1066Class::Contract provides an explicit syntax for defining the attributes,
1067methods, and constructors of a class. The class itself is defined using
1068the C<contract> subroutine. C<contract> takes a single argument -- a
1069subroutine reference or a block. That block is executed once and the
1070results used to construct and install the various components of the
1071class in the current package:
1072
1073        package Queue;
1074        contract {
1075          # specification of class Queue attributes and methods here
1076        };
1077
1078=head2 Defining attributes
1079
1080Attributes are defined within the C<contract> block via the C<attr> subroutine.
1081Attributes must be given a name, and may also be given a type: C<SCALAR>,
1082C<ARRAY>, C<HASH>, or a class name:
1083
1084        contract {
1085                attr 'last';                   # Scalar attribute (by default)
1086                attr 'lest' => SCALAR;         # Scalar attribute
1087                attr 'list' => ARRAY;          # Array attribute
1088                attr 'lost' => HASH;           # Hash attribute
1089                attr 'lust' => MyClass;        # Object attribute
1090        };
1091
1092For each attribute so declared, Class::Contract creates an I<accessor> -- a
1093method that returns a reference to the attribute in question. Code using these
1094accessors might look like this:
1095
1096        ${$obj->last}++;
1097        push @{$obj->list}, $newitem;
1098        print $obj->lost->{'marbles'};
1099        $obj->lust->after('technology stocks');
1100
1101Attributes are normally object-specific, but it is also possible to define
1102attributes that are shared by all objects of a class. Class objects are
1103specified by prefixing the call to C<attr> with a call to the C<class>
1104subroutine:
1105
1106        class Queue;
1107        contract {
1108                class attr 'obj_count';
1109        };
1110
1111The accessor for this shared attribute can now be called either as an
1112object method:
1113
1114        print ${$obj->obj_count};
1115
1116or as a class method:
1117
1118        print ${Queue->obj_count};
1119
1120In order to ensure that the clauses of a class' contract (see below)
1121are honoured, both class and object attributes are only accessible via
1122their accessors, and those accessors may only be called within methods
1123belonging to the same class hierarchy. Objects are implemented as
1124"flyweight scalars" in order to ensure this strict encapsulation is
1125preserved.
1126
1127=head2 Defining methods
1128
1129Methods are defined in much the same way as attributes. The C<method>
1130subroutine is used to specify the name of a method, then the C<impl>
1131subroutine is used to provide an implementation for it:
1132
1133        contract {
1134                attr list => ARRAY;
1135
1136                method 'next';
1137                    impl { shift @{self->list} };
1138
1139                method 'enqueue';
1140                    impl { push @{self->list}, $_[1] };
1141        };
1142
1143C<impl> takes a block (or a reference to a subroutine), which is used as
1144the implementation of the method named by the preceding C<method> call.
1145Within that block, the subroutine C<self> may be used to return a
1146reference to the object on which the method was called. Unlike, regular
1147OO Perl, the object reference is not passed as the method's first argument.
1148(Note: this change occurred in version 1.10)
1149
1150Like attributes, methods normally belong to -- and are accessed via -- a
1151specific object. To define methods that belong to the entire class, the
1152C<class> qualifier is once again used:
1153
1154        contract {
1155                class attr 'obj_count';
1156
1157                class method 'inc_count';
1158                        impl { ${self->obj_count}++ };
1159        };
1160
1161Note that the C<self> subroutine can still be used -- within a class
1162method it returns the appropriate class name, rather than an object
1163reference.
1164
1165=head2 Defining constructors
1166
1167Class::Contract requires constructors to be explicitly defined using
1168the C<ctor> subroutine:
1169
1170        contract {
1171                ctor 'new';
1172                    impl { @{self->list} = ( $_[0] ) }
1173        };
1174
1175Note that the implementation section of a constructor I<doesn't> specify
1176code to build or bless the new object. That is taken care of
1177automatically (in order to ensure the correct "flyweight"
1178implementation of the object).
1179
1180Instead, the constructor implementation is invoked I<after> the object
1181has been created and blessed into the class. Hence the implementation
1182only needs to initialize the various attributes of the C<self> object.
1183In addition, the return value of the implementation is ignored:
1184constructor calls always return a reference to the newly created object.
1185
1186Any attribute that is not initialized by a constructor is
1187automatically "default initialized". By default, scalar attributes
1188remain C<undef>, array and hash attributes are initialized to an empty
1189array or hash, and object attributes are initialized by having their
1190C<new> constructor called (with no arguments). This is the only
1191reasonable default for object attributes, but it is usually advisable to
1192initialize them explicitly in the constructor.
1193
1194It is also possible to define a "class constructor", which may be used
1195to initialize class attributes:
1196
1197        contract {
1198                class attr 'obj_count';
1199
1200                class ctor;
1201                        impl { ${self->obj_count} = 0 };
1202        };
1203
1204The class constructor is invoked at the very end of the call to
1205C<contract> in which the class is defined.
1206
1207Note too that the class constructor does not require a name. It may,
1208however, be given one, so that it can be explicitly called again (as a
1209class method) later in the program:
1210
1211        class MyClass;
1212        contract {
1213                class attr 'obj_count';
1214
1215                class ctor 'reset';
1216                        impl { ${self->obj_count} = 0 };
1217        };
1218
1219        # and later...
1220
1221        MyClass->reset;
1222
1223
1224=head2 Defining destructors
1225
1226Destructors are also explicitly defined under Class::Contract,
1227using the C<dtor> subroutine:
1228
1229        contract {
1230                dtor;
1231                    impl { print STDLOG "Another object died\n" }
1232        };
1233
1234As with the constructor, the implementation section of a destructor
1235doesn't specify code to clean up the "flyweight" implementation of
1236the object. Class::Contract takes care of that automatically.
1237
1238Instead, the implementation is invoked I<before> the object is
1239deallocated, and may be used to clean up any of the internal structure
1240of the object (for example to break reference cycles).
1241
1242It is also possible to define a "class destructor", which may be used
1243to clean up class attributes:
1244
1245        contract {
1246                class attr 'obj_count';
1247
1248                class dtor;
1249                    impl { print STDLOG "Total was ${self->obj_count}\n" };
1250        };
1251
1252The class destructor is invoked from an C<END> block within Class::Contract
1253(although the implementation itself is a closure, so it executes in the
1254namespace of the original class).
1255
1256
1257=head2 Constraining class elements
1258
1259As described so far, Class::Contract doesn't provide any features that
1260differ greatly from those of any other class definition module. But
1261Class::Contract does have one significant difference: it allows the
1262class designer to specify "clauses" that implement and enforce a
1263contract on the class's interface.
1264
1265Contract clauses are specified as labelled blocks of code, associated
1266with a particular class, method, or attribute definition.
1267
1268=head2 Class invariants
1269
1270Classes may be given I<invariants>: clauses than must be satisfied at
1271the end of any method call that is invoked from outside the class
1272itself. For example, to specify that a class's object count attribute
1273must never fall below zero:
1274
1275        contract {
1276                invar { ${self->obj_count} >= 0 };
1277        };
1278
1279The block following C<invar> is treated as if it were a class method
1280that is automatically invoked after every other method invocation. If the
1281method returns false, C<croak> is invoked with the error message:
1282C<'Class invariant at %s failed'> (where the C<'%s'> is replaced by the file
1283and line number at which the invariant was defined).
1284
1285This error message can be customized, using the C<failmsg> subroutine:
1286
1287        contract {
1288                invar { ${self->obj_count} >= 0 };
1289                    failmsg 'Anti-objects detected by invariant at %s';
1290        };
1291
1292Once again, the C<'%s'> is replaced by the appropriate file name and
1293line number. A C<failmsg> can be specified after other types of clause
1294too (see below).
1295
1296A class may have as many invariants as it requires, and
1297they may be specified anywhere throughout the the body of the C<contract>.
1298
1299=head2 Attribute and method pre- and post-conditions
1300
1301Pre- and post-conditions on methods and attributes are specified
1302using the C<pre> and C<post> subroutines respectively.
1303
1304For attributes, pre-conditions are called before the attribute's
1305accessor is invoked, and post-conditions are called after the reference
1306returned by the accessor is no longer accessible. This is
1307achieved by having the accessor return a tied scalar whose C<DESTROY>
1308method invokes the post-condition.
1309
1310Method pre-conditions are tested before their method's implementation is
1311invoked; post-conditions are tested after the implementation finishes
1312(but before the method's result is returned). Constructors are (by
1313definition) class methods and may have pre- and post-conditions, just
1314like any other method.
1315
1316Both types of condition clause receive the same argument list as the
1317accessor or method implementation that they constrain. Both are expected
1318to return a false value if they fail:
1319
1320        contract {
1321                class attr 'obj_count';
1322                    post { ${&value} > 0 };
1323                      failmsg 'Anti-objects detected by %s';
1324
1325                method 'inc_count';
1326                    post { ${self->obj_count} < 1000000 };
1327                      failmsg 'Too many objects!';
1328                    impl { ${self->obj_count}++ };
1329        };
1330
1331Note that within the pre- and post-conditions of an attribute, the
1332special C<value> subroutine returns a reference to the attribute itself,
1333so that conditions can check properties of the attribute they guard.
1334
1335Methods and attributes may have as many distinct pre- and
1336post-conditions as they require, specified in any convenient order.
1337
1338
1339=head2 Checking state changes.
1340
1341Post-conditions and invariants can access the previous state of an object or
1342the class, via the C<old> subroutine. Within any post-condition or invariant,
1343this subroutine returns a reference to a copy of the object or class
1344state, as it was just before the current method or accessor was called.
1345
1346For example, an C<append> method might use C<old> to verify the appropriate
1347change in size of an object:
1348
1349        contract {
1350            method 'append';
1351                post { @{self->queue} == @{old->queue} + @_ }
1352                impl { push @{self->queue}, @_ };
1353        };
1354
1355Note that the implementation's return value is also available in the
1356method's post-condition(s) and the class's invariants, through the
1357subroutine C<value>. In the above example, the implementation of C<append>
1358returns the new size of the queue (i.e. what C<push> returns), so the
1359post-condition could also be written:
1360
1361        contract {
1362            method 'append';
1363                post { ${&value} == @{old->queue} + @_ }
1364                impl { push @{self->queue}, @_ };
1365        };
1366
1367Note that C<value> will return a reference to a scalar or to
1368an array, depending on the context in which the method was originally
1369called.
1370
1371
1372=head2 Clause control
1373
1374Any type of clause may be declared optional:
1375
1376        contract {
1377                optional invar { @{self->list} > 0 };
1378                failmsg 'Empty queue detected at %s after call';
1379        };
1380
1381By default, optional clauses are still checked every time a method or
1382accessor is invoked, but they may also be switched off (and back on) at
1383run-time, using the C<check> method:
1384
1385        local $_ = 'Queue';         # Specify in $_ which class to disable
1386        check my %contract => 0;    # Disable optional checks for class Queue
1387
1388This (de)activation is restricted to the scope of the hash that is passed as
1389the first argument to C<check>. In addition, the change only affects the
1390class whose name is held in the variable $_ at the time C<check> is called.
1391This makes it easy to (de)activate checks for a series of classes:
1392
1393        check %contract => 0 for qw(Queue PriorityQueue DEQueue);  # Turn off
1394        check %contract => 1 for qw(Stack PriorityStack Heap);     # Turn on
1395
1396
1397The special value C<'__ALL__'> may also be used as a (pseudo-)class name:
1398
1399        check %contract => 0 for __ALL__;
1400
1401This enables or disables checking on every class defined using
1402Class::Contract. But note that only clauses that were originally
1403declared C<optional> are affected by calls to C<check>. Non-optional
1404clauses are I<always> checked.
1405
1406Optional clauses are typically universally disabled in production code,
1407so Class::Contract provides a short-cut for this. If the module is
1408imported with the single argument C<'production'>, optional clauses
1409are universally and irrevocably deactivated. In fact, the C<optional>
1410subroutine is replaced by:
1411
1412        sub Class::Contract::optional {}
1413
1414so that optional clauses impose no run-time overhead at all.
1415
1416In production code, contract checking ought to be disabled completely,
1417and the requisite code optimized away.  To do that, simply change:
1418
1419  use Class::Contract;
1420
1421to
1422
1423  use Class::Contract::Production;
1424
1425
1426=head2 Inheritance
1427
1428The semantics of class inheritance for Class::Contract classes
1429differ in several respects from those of normal object-oriented Perl.
1430
1431To begin with, classes defined using Class::Contract have a I<static
1432inheritance hierarchy>. The inheritance relationships of contracted classes
1433are defined using the C<inherits> subroutine within the class's C<contract>
1434block:
1435
1436        package PriorityQueue;
1437        contract {
1438                inherits qw( Queue OrderedContainer );
1439        };
1440
1441
1442That means that ancestor classes are fixed at compile-time
1443(rather than being determined at run-time by the @ISA array). Note
1444that multiple inheritance is supported.
1445
1446Method implementations are only inherited if they are not explicitly
1447provided. As with normal OO Perl, a method's implementation is inherited
1448from the left-most ancestral class that provides a method of the same name
1449(though with Class::Contract, this is determined at compile-time).
1450
1451Constructors are a special case, however. Their "constructive"
1452behaviour is always specific to the current class, and hence involves
1453no inheritance under any circumstances. However, the "initialising"
1454behaviour specified by a constructor's C<impl> block I<is> inherited. In
1455fact, the implementations of I<all> base class constructors are
1456called automatically by the derived class constructor (in left-most,
1457depth-first order), and passed the same argument list as the invoked
1458constructor. This behaviour is much more like that of other OO
1459programming languages (for example, Eiffel or C++).
1460
1461Methods in a base class can also be declared as being I<abstract>:
1462
1463        contract {
1464            abstract method 'remove';
1465                post { ${self->count} == ${old->count}-1 };
1466        };
1467
1468Abstract methods act like placeholders in an inheritance hierarchy.
1469Specifically, they have no implementation, existing only to reserve
1470the name of a method and to associate pre- and post-conditions with it.
1471
1472An abstract method cannot be directly called (although its associated
1473conditions may be). If such a method is ever invoked, it immediately
1474calls C<croak>. Therefore, the presence of an abstract method in a base
1475class requires the derived class to redefine that method, if the
1476derived class is to be usable. To ensure this, any constructor built by
1477Class::Contract will refuse to create objects belonging to classes with
1478abstract methods.
1479
1480Methods in a base class can also be declared as being I<private>:
1481
1482        contract {
1483            private method 'remove';
1484                impl { pop @{self->queue} };
1485        };
1486
1487Private methods may only be invoked by the class or one of its
1488descendants.
1489
1490=head2 Inheritance and condition checking
1491
1492Attribute accessors and object methods inherit I<all> post-conditions of
1493every ancestral accessor or method of the same name. Objects and classes
1494also inherit all invariants from any ancestor classes. That is,
1495methods accumulate all the post- and invariant checks that their
1496ancestors performed, as well as any new ones they define for themselves,
1497and must satisfy I<all> of them in order to execute successfully.
1498
1499Pre-conditions are handled slightly differently. The principles of
1500design-by-contract programming state that pre-conditions in derived
1501classes can be no stronger than those in base classes (and may well be
1502weaker). In other words, a derived class must handle every case that
1503its base class handled, but may choose to handle other cases as well,
1504by being less demanding regarding its pre-conditions.
1505
1506Meyers suggests an efficient way to achieve this relaxation of
1507constraints without the need for detailed logical analysis of
1508pre-conditions. His solution is to allow a derived class method or
1509accessor to run if I<either> the pre-conditions it inherits are
1510satisfied I<or> its own pre-conditions are satisfied. This is precisely
1511the semantics that Class::Contract uses when checking pre-conditions in
1512derived classes.
1513
1514=head2 A complete example
1515
1516The following code implements a PriorityStack class, in which elements pushed
1517onto the stack "sink" until they encounter an element with lower priority.
1518Note the use of C<old> to check that object state has changed correctly, and
1519the use of explicit dispatch (e.g. C<self-E<gt>Stack::pop>) to invoke
1520inherited methods from the derived-class methods that redefine them.
1521
1522        package PriorityStack;
1523        use Class::Contract;
1524
1525        contract {
1526            # Reuse existing implementation...
1527            inherits 'Stack';
1528
1529            # Name the constructor (nothing special to do, so no implementation)
1530            ctor 'new';
1531
1532            method 'push';
1533                # Check that data to be added is okay...
1534                pre  { defined $_[0] };
1535                    failmsg 'Cannot push an undefined value';
1536                pre  { $_[1] > 0 };
1537                    failmsg 'Priority must be greater than zero';
1538
1539                # Check that push increases stack depth appropriately...
1540                post { self->count == old->count+1 };
1541
1542                # Check that the right thing was left on top...
1543                post { old->top->{'priority'} <= self->top->{'priority'} };
1544
1545                # Implementation reuses inherited methods: pop any higher
1546                # priority entries, push the new entry, then re-bury it...
1547                impl {
1548                    my ($newval, $priority) = @_[0,1];
1549                    my @betters;
1550                    unshift @betters, self->Stack::pop
1551                        while self->count
1552                           && self->Stack::top->{'priority'} > $priority;
1553                    self->Stack::push( {'val'=>$newval, priority=>$priority} );
1554                    self->Stack::push( $_ )  foreach @betters;
1555                };
1556
1557            method 'pop';
1558                # Check that pop decreases stack depth appropriately...
1559                post { self->count == old->count-1 };
1560
1561                # Reuse inherited method...
1562                impl {
1563                    return  unless self->count;
1564                    return self->Stack::pop->{'val'};
1565                };
1566
1567            method 'top';
1568                post { old->count == self->count }
1569                impl {
1570                    return  unless self->count;
1571                    return self->Stack::top->{'val'};
1572                };
1573        };
1574
1575
1576=head1 FUTURE WORK
1577
1578Future work on Class::Contract will concentrate on three areas:
1579
1580=over 4
1581
1582=item 1.  Improving the attribute accessor mechanism
1583
1584Lvalue subroutines will be introduced in perl version 5.6. They will allow
1585a return value to be treated as an alias for the (scalar) argument of a
1586C<return> statement. This will make it possible to write subroutines whose
1587return value may be assigned to (like the built-in C<pos> and C<substr>
1588functions).
1589
1590In the absence of this feature, Class::Contract accessors of all types
1591return a reference to their attribute, which then requires an explicit
1592dereference:
1593
1594        ${self->value} = $newval;
1595        ${self->access_count}++;
1596
1597When this feature is available, accessors for scalar attributes will be
1598able to return the actual attribute itself as an lvalue. The above code
1599would then become cleaner:
1600
1601        self->value = $newval;
1602        self->access_count++;
1603
1604
1605=item 2.  Providing better software engineering tools.
1606
1607Contracts make the consequences of inheritance harder to predict, since
1608they significantly increase the amount of ancestral behaviour (i.e.
1609contract clauses) that a class inherits.
1610
1611Languages such as Eiffel provide useful tools to help the
1612software engineer make sense of this extra information. In
1613particular, Eiffel provides two alternate ways of inspecting a
1614particular class -- flat form and short form.
1615
1616"Flattening" a class produces an equivalent class definition without any
1617inheritance. That is, the class is modified by making explicit all the
1618attributes, methods, conditions, and invariants it inherits from other
1619classes. This allows the designer to see every feature a class possesses
1620in one location.
1621
1622"Shortening" a class, takes the existing class definition and removes all
1623implementation aspects of it -- that is, those that have no bearing on its
1624public interface. A shortened representation of a class therefore has all
1625attribute specifications and method implementations removed. Note that
1626the two processes can be concatenated: shortening a flattened class
1627produces an explicit listing of its complete public interface. Such a
1628representation can be profitably used as a basis for documenting the
1629class.
1630
1631It is envisaged that Class::Contract will eventually provide a mechanism to
1632produce equivalent class representations in Perl.
1633
1634
1635=item 3.  Offering better facilities for retrofitting contracts.
1636
1637At present, adding contractual clauses to an existing class requires a
1638major restructuring of the original code. Clearly, if design-by-contract
1639is to gain popularity with Perl programmers, this transition cost must
1640be minimized.
1641
1642It is as yet unclear how this might be accomplished, but one possibility
1643would be to allow the implementation of certain parts of a
1644Class::Contract class (perhaps even the underlying object implementation
1645itself) to be user-defined.
1646
1647=back
1648
1649=head1 AUTHOR
1650
1651Damian Conway (damian@conway.org)
1652
1653=head1 MAINTAINER
1654
1655C. Garrett Goebel (ggoebel@cpan.org)
1656
1657=head1 BUGS
1658
1659There are undoubtedly serious bugs lurking somewhere in code this funky :-)
1660Bug reports and other feedback are most welcome.
1661
1662=head1 COPYRIGHT
1663
1664Copyright (c) 1997-2000, Damian Conway. All Rights Reserved.
1665This module is free software. It may be used, redistributed
1666and/or modified under the terms of the Perl Artistic License
1667  (see http://www.perl.com/perl/misc/Artistic.html)
1668
1669Copyright (c) 2000-2001, C. Garrett Goebel. All Rights Reserved.
1670This module is free software. It may be used, redistributed
1671and/or modified under the terms of the Perl Artistic License
1672  (see http://www.perl.com/perl/misc/Artistic.html)
1673