| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Class::Agreement; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 19 |  |  | 19 |  | 706812 | use warnings; | 
|  | 19 |  |  |  |  | 48 |  | 
|  | 19 |  |  |  |  | 649 |  | 
| 4 | 19 |  |  | 19 |  | 99 | use strict; | 
|  | 19 |  |  |  |  | 40 |  | 
|  | 19 |  |  |  |  | 942 |  | 
| 5 |  |  |  |  |  |  |  | 
| 6 |  |  |  |  |  |  | our $VERSION = '0.02'; | 
| 7 |  |  |  |  |  |  |  | 
| 8 | 19 |  |  | 19 |  | 162 | use Carp; | 
|  | 19 |  |  |  |  | 37 |  | 
|  | 19 |  |  |  |  | 2297 |  | 
| 9 | 19 |  |  | 19 |  | 20712 | use Class::Inspector; | 
|  | 19 |  |  |  |  | 85666 |  | 
|  | 19 |  |  |  |  | 703 |  | 
| 10 | 19 |  |  | 19 |  | 639 | use Scalar::Util qw(blessed); | 
|  | 19 |  |  |  |  | 35 |  | 
|  | 19 |  |  |  |  | 4211 |  | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | =head1 NAME | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | Class::Agreement - add contracts to your Perl classes easily | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | package SomeClass; | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | use Class::Agreement; | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | # use base 'Class::Accessor' or 'Class::MethodMaker', | 
| 23 |  |  |  |  |  |  | # or roll your own: | 
| 24 |  |  |  |  |  |  | sub new { ... } | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | invariant { | 
| 27 |  |  |  |  |  |  | my ($self) = @_; | 
| 28 |  |  |  |  |  |  | $self->count > 0; | 
| 29 |  |  |  |  |  |  | }; | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | precondition add_a_positive => sub { | 
| 32 |  |  |  |  |  |  | my ( $self, $value ) = @_; | 
| 33 |  |  |  |  |  |  | return ( $value >= 0 ); | 
| 34 |  |  |  |  |  |  | }; | 
| 35 |  |  |  |  |  |  | sub add_a_positive { | 
| 36 |  |  |  |  |  |  | my ( $self, $value ) = @_; | 
| 37 |  |  |  |  |  |  | ... | 
| 38 |  |  |  |  |  |  | } | 
| 39 |  |  |  |  |  |  |  | 
| 40 |  |  |  |  |  |  | sub choose_word { | 
| 41 |  |  |  |  |  |  | my ( $self, $value ) = @_; | 
| 42 |  |  |  |  |  |  | ... | 
| 43 |  |  |  |  |  |  | } | 
| 44 |  |  |  |  |  |  | postcondition choose_word => sub { | 
| 45 |  |  |  |  |  |  | return ( result >= 0 ); | 
| 46 |  |  |  |  |  |  | }; | 
| 47 |  |  |  |  |  |  |  | 
| 48 |  |  |  |  |  |  | dependent increase_foo => sub { | 
| 49 |  |  |  |  |  |  | my ( $self, $amount ) = @_; | 
| 50 |  |  |  |  |  |  | my $old_foo = $self->foo; | 
| 51 |  |  |  |  |  |  | return sub { | 
| 52 |  |  |  |  |  |  | my ( $self, $amount ) = @_; | 
| 53 |  |  |  |  |  |  | return ( $old_foo < $self->get_foo ); | 
| 54 |  |  |  |  |  |  | } | 
| 55 |  |  |  |  |  |  | }; | 
| 56 |  |  |  |  |  |  | sub increase_foo { | 
| 57 |  |  |  |  |  |  | my ( $self, $amount ) = @_; | 
| 58 |  |  |  |  |  |  | $self->set_foo( $self->get_foo + $amount ); | 
| 59 |  |  |  |  |  |  | } | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | Class::Agreement is an implementation of behavioral contracts for Perl5. This | 
| 64 |  |  |  |  |  |  | module allows you to easily add pre- and postconditions to new or existing Perl | 
| 65 |  |  |  |  |  |  | classes. | 
| 66 |  |  |  |  |  |  |  | 
| 67 |  |  |  |  |  |  | This module provides contracts such as dependent contracts, contracts for | 
| 68 |  |  |  |  |  |  | higher-order functions, and informative messages when things fail. At the time | 
| 69 |  |  |  |  |  |  | of this writing, Class::Agreement is one of only two contract implementations | 
| 70 |  |  |  |  |  |  | that blames contract-breaking components correctly.  (See: "Object-oriented | 
| 71 |  |  |  |  |  |  | Programming Languages Need Well-founded Contracts" at | 
| 72 |  |  |  |  |  |  | L.) | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  | Using Class::Agreement lets you specify proper input and output of your | 
| 75 |  |  |  |  |  |  | functions or methods, thus strengthening your code and allowing you to spot | 
| 76 |  |  |  |  |  |  | bugs earlier. | 
| 77 |  |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  | =head2 Comparison with Class::Contract | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | L requires you to use its own object and accessor system, which | 
| 81 |  |  |  |  |  |  | makes the addition of contracts to existing code difficult. In contrast, it | 
| 82 |  |  |  |  |  |  | should be easy to implement contracts with L no matter what | 
| 83 |  |  |  |  |  |  | object system (C, L, L, etc.) you | 
| 84 |  |  |  |  |  |  | use. | 
| 85 |  |  |  |  |  |  |  | 
| 86 |  |  |  |  |  |  | L also clones objects every time you add a postcondition, which | 
| 87 |  |  |  |  |  |  | can get pretty expensive. L doesn't clone -- alternatively, it | 
| 88 |  |  |  |  |  |  | provides you with dependent contracts so that you can use closure to keep track | 
| 89 |  |  |  |  |  |  | of only the values you care about. (See L"Testing old values">.) | 
| 90 |  |  |  |  |  |  |  | 
| 91 |  |  |  |  |  |  | =head2 Comparison with Eiffel | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | You could say that L gives you Perl equivalents of Eiffel's | 
| 94 |  |  |  |  |  |  | C, C, C and (indirectly) C keywords. For | 
| 95 |  |  |  |  |  |  | example, the following Eiffel method: | 
| 96 |  |  |  |  |  |  |  | 
| 97 |  |  |  |  |  |  | decrement is | 
| 98 |  |  |  |  |  |  | require | 
| 99 |  |  |  |  |  |  | item > 0 | 
| 100 |  |  |  |  |  |  | do | 
| 101 |  |  |  |  |  |  | item := item - 1 | 
| 102 |  |  |  |  |  |  | ensure | 
| 103 |  |  |  |  |  |  | item = old item - 1 | 
| 104 |  |  |  |  |  |  | end | 
| 105 |  |  |  |  |  |  |  | 
| 106 |  |  |  |  |  |  | ...could be written in Perl as: | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  | use Class::Contract; | 
| 109 |  |  |  |  |  |  | ... | 
| 110 |  |  |  |  |  |  |  | 
| 111 |  |  |  |  |  |  | precondition decrement => sub { shift()->item > 0 } | 
| 112 |  |  |  |  |  |  |  | 
| 113 |  |  |  |  |  |  | sub decrement { | 
| 114 |  |  |  |  |  |  | my ( $self ) = @_; | 
| 115 |  |  |  |  |  |  | $self->item( $self->item - 1 ); | 
| 116 |  |  |  |  |  |  | } | 
| 117 |  |  |  |  |  |  |  | 
| 118 |  |  |  |  |  |  | dependent decrement => sub { | 
| 119 |  |  |  |  |  |  | my ( $self ) = @_; | 
| 120 |  |  |  |  |  |  | my $old_item = $self->item; | 
| 121 |  |  |  |  |  |  | return sub { $self->item == $old_item - 1 }; | 
| 122 |  |  |  |  |  |  | }; | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | =head1 EXPORT | 
| 125 |  |  |  |  |  |  |  | 
| 126 |  |  |  |  |  |  | The following functions are exported by default: | 
| 127 |  |  |  |  |  |  |  | 
| 128 |  |  |  |  |  |  | =over 4 | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  | =item * C, C, and C, each of which have two distinct calling syntaxes: one for functional programming and one for object-oriented. | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | =item * C, which should only be used within postconditions or functions returned by dependent contracts. | 
| 133 |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  | =item * C and C, both of which are used only in object-oriented programming. | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  | =back | 
| 137 |  |  |  |  |  |  |  | 
| 138 |  |  |  |  |  |  | All exported functions are described in the following section, L"FUNCTIONS">. | 
| 139 |  |  |  |  |  |  |  | 
| 140 |  |  |  |  |  |  | =cut | 
| 141 |  |  |  |  |  |  |  | 
| 142 | 19 |  |  | 19 |  | 112 | use base 'Exporter'; | 
|  | 19 |  |  |  |  | 36 |  | 
|  | 19 |  |  |  |  | 3787 |  | 
| 143 |  |  |  |  |  |  |  | 
| 144 |  |  |  |  |  |  | our @EXPORT = qw( | 
| 145 |  |  |  |  |  |  | result | 
| 146 |  |  |  |  |  |  | precondition postcondition dependent invariant | 
| 147 |  |  |  |  |  |  | specify_constructors | 
| 148 |  |  |  |  |  |  | ); | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  | my $contracts = {}; | 
| 151 |  |  |  |  |  |  |  | 
| 152 |  |  |  |  |  |  | my $constructors = {}; | 
| 153 |  |  |  |  |  |  |  | 
| 154 |  |  |  |  |  |  | # | 
| 155 |  |  |  |  |  |  | # a separate subroutine is necessary to keep the exported function prototype | 
| 156 |  |  |  |  |  |  | # | 
| 157 |  |  |  |  |  |  | sub _real_result { | 
| 158 | 1 |  |  | 1 |  | 27 | croak "function Class::Agreement::result() used outside of postcondition"; | 
| 159 |  |  |  |  |  |  | } | 
| 160 |  |  |  |  |  |  |  | 
| 161 |  |  |  |  |  |  | sub result () { | 
| 162 | 101 |  |  | 101 | 1 | 474 | goto &_real_result; | 
| 163 |  |  |  |  |  |  | } | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  |  |  |  | sub _parent_class_of_method { | 
| 166 |  |  |  |  |  |  |  | 
| 167 |  |  |  |  |  |  | # based off find_parent from SUPER.pm by Simon Cozens/chromatic | 
| 168 | 73 |  |  | 73 |  | 144 | my ( $class, $method, $prune ) = @_; | 
| 169 | 73 |  | 50 |  |  | 374 | $prune ||= ''; | 
| 170 |  |  |  |  |  |  | { | 
| 171 | 19 |  |  | 19 |  | 110 | no strict 'refs'; | 
|  | 19 |  |  |  |  | 38 |  | 
|  | 19 |  |  |  |  | 2473 |  | 
|  | 73 |  |  |  |  | 102 |  | 
| 172 | 73 |  |  |  |  | 110 | for my $parent ( @{ $class . '::ISA' }, 'UNIVERSAL' ) { | 
|  | 73 |  |  |  |  | 300 |  | 
| 173 | 73 | 50 |  |  |  | 188 | return _parent_class_of_method( $parent, $method ) | 
| 174 |  |  |  |  |  |  | if $parent eq $prune; | 
| 175 | 73 | 100 |  |  |  | 846 | return $parent if $parent->can($method); | 
| 176 |  |  |  |  |  |  | } | 
| 177 |  |  |  |  |  |  | } | 
| 178 |  |  |  |  |  |  | } | 
| 179 |  |  |  |  |  |  |  | 
| 180 |  |  |  |  |  |  | sub _subroutine_exists { | 
| 181 | 219 |  |  | 219 |  | 380 | my ($symbol) = @_; | 
| 182 | 19 |  |  | 19 |  | 121 | no strict 'refs'; | 
|  | 19 |  |  |  |  | 61 |  | 
|  | 19 |  |  |  |  | 3921 |  | 
| 183 | 219 |  |  |  |  | 259 | *{$symbol}{CODE}; | 
|  | 219 |  |  |  |  | 1476 |  | 
| 184 |  |  |  |  |  |  | } | 
| 185 |  |  |  |  |  |  |  | 
| 186 |  |  |  |  |  |  | sub _check_arguments { | 
| 187 | 99 |  |  | 99 |  | 204 | my ( $glob, $block ) = @_; | 
| 188 | 99 |  |  |  |  | 272 | my $caller_name = [ caller(1) ]->[3]; | 
| 189 | 99 | 50 |  |  |  | 2226 | croak "first argument to $caller_name() was undefined" | 
| 190 |  |  |  |  |  |  | unless defined $glob; | 
| 191 | 99 | 50 |  |  |  | 367 | croak "second argument to $caller_name() was not a subroutine reference" | 
| 192 |  |  |  |  |  |  | unless ref $block eq 'CODE'; | 
| 193 |  |  |  |  |  |  | } | 
| 194 |  |  |  |  |  |  |  | 
| 195 |  |  |  |  |  |  | sub _add_contract_for_hierarchy { | 
| 196 | 84 |  |  | 84 |  | 202 | my ( $package, $glob, $type, $inforef ) = @_; | 
| 197 |  |  |  |  |  |  |  | 
| 198 |  |  |  |  |  |  | # if they're trying to add a contract to a method that isn't overridden, | 
| 199 |  |  |  |  |  |  | # create a stub to attach the contract to | 
| 200 | 84 |  |  |  |  | 294 | my $this_symbol = _package_and_method_to_symbol( $package, $glob ); | 
| 201 | 84 | 100 |  |  |  | 248 | if ( not _subroutine_exists($this_symbol) ) { | 
| 202 | 19 |  |  | 19 |  | 132 | no strict 'refs'; | 
|  | 19 |  |  |  |  | 33 |  | 
|  | 19 |  |  |  |  | 6228 |  | 
| 203 | 2 | 100 |  |  |  | 7 | if ( my $parent = _parent_class_of_method( $package, $glob ) ) { | 
| 204 | 1 |  |  |  |  | 6 | *{$this_symbol} = $parent->can($glob); | 
|  | 1 |  |  |  |  | 7 |  | 
| 205 |  |  |  |  |  |  | } | 
| 206 |  |  |  |  |  |  | else { | 
| 207 | 1 |  |  |  |  | 11 | croak | 
| 208 |  |  |  |  |  |  | "can't add $type contract to undefined subroutine $this_symbol"; | 
| 209 |  |  |  |  |  |  | } | 
| 210 |  |  |  |  |  |  | } | 
| 211 |  |  |  |  |  |  |  | 
| 212 |  |  |  |  |  |  | my @classes | 
| 213 | 83 | 100 |  |  |  | 131 | = ( $package, @{ Class::Inspector->subclasses($package) || [] } ); | 
|  | 83 |  |  |  |  | 437 |  | 
| 214 | 83 |  |  |  |  | 1265505 | foreach my $source_class (@classes) { | 
| 215 | 135 |  |  |  |  | 553 | my $symbol = _package_and_method_to_symbol( $source_class, $glob ); | 
| 216 | 135 | 100 |  |  |  | 400 | _add_contract( $symbol, $type, $inforef, $package ) | 
| 217 |  |  |  |  |  |  | if _subroutine_exists($symbol); | 
| 218 |  |  |  |  |  |  | } | 
| 219 |  |  |  |  |  |  | } | 
| 220 |  |  |  |  |  |  |  | 
| 221 |  |  |  |  |  |  | sub _add_contract { | 
| 222 | 118 |  |  | 118 |  | 364 | my ( $symbol, $type, $inforef, $source_class ) = @_; | 
| 223 |  |  |  |  |  |  |  | 
| 224 |  |  |  |  |  |  | # if we already have a contract of this type... | 
| 225 | 118 | 100 |  |  |  | 388 | if ( my @contracts = _get_contracts( $symbol, $type ) ) { | 
| 226 |  |  |  |  |  |  |  | 
| 227 |  |  |  |  |  |  | # if this contract wasn't defined by our source class.. | 
| 228 | 28 | 100 |  |  |  | 115 | if ( $contracts[0]->[3] ne $source_class ) { | 
| 229 |  |  |  |  |  |  |  | 
| 230 |  |  |  |  |  |  | # erase any existing contracts | 
| 231 | 13 |  |  |  |  | 71 | _erase_contracts( $symbol, $type ); | 
| 232 |  |  |  |  |  |  | } | 
| 233 |  |  |  |  |  |  | } | 
| 234 |  |  |  |  |  |  |  | 
| 235 |  |  |  |  |  |  | # add our new contract | 
| 236 | 118 |  |  |  |  | 199 | push @{ $contracts->{$symbol}{$type} }, [ @$inforef, $source_class ]; | 
|  | 118 |  |  |  |  | 660 |  | 
| 237 |  |  |  |  |  |  |  | 
| 238 |  |  |  |  |  |  | # if the symbol doesn't have a wrapper, add one | 
| 239 | 118 | 100 |  |  |  | 578 | if ( not _has_a_contract($symbol) ) { | 
| 240 | 71 |  |  |  |  | 311 | _set_implementation( $symbol, \&$symbol ); | 
| 241 | 19 |  |  | 19 |  | 338 | no strict 'refs'; | 
|  | 19 |  |  |  |  | 36 |  | 
|  | 19 |  |  |  |  | 573 |  | 
| 242 | 19 |  |  | 19 |  | 99 | no warnings 'redefine'; | 
|  | 19 |  |  |  |  | 32 |  | 
|  | 19 |  |  |  |  | 33222 |  | 
| 243 | 71 |  |  |  |  | 233 | *{$symbol} = _make_method_wrapper($symbol); | 
|  | 71 |  |  |  |  | 793 |  | 
| 244 |  |  |  |  |  |  | } | 
| 245 |  |  |  |  |  |  | } | 
| 246 |  |  |  |  |  |  |  | 
| 247 |  |  |  |  |  |  | sub _set_implementation { | 
| 248 | 71 |  |  | 71 |  | 154 | my ( $symbol, $block ) = @_; | 
| 249 | 71 |  |  |  |  | 212 | $contracts->{$symbol}{impl} = $block; | 
| 250 |  |  |  |  |  |  | } | 
| 251 |  |  |  |  |  |  |  | 
| 252 |  |  |  |  |  |  | sub _get_implementation { | 
| 253 | 96 |  |  | 96 |  | 230 | my ($symbol) = @_; | 
| 254 | 96 |  |  |  |  | 267 | return $contracts->{$symbol}{impl}; | 
| 255 |  |  |  |  |  |  | } | 
| 256 |  |  |  |  |  |  |  | 
| 257 |  |  |  |  |  |  | sub _has_a_contract { | 
| 258 | 118 |  |  | 118 |  | 277 | my ($symbol) = @_; | 
| 259 | 118 |  |  |  |  | 823 | return exists $contracts->{$symbol}{impl}; | 
| 260 |  |  |  |  |  |  | } | 
| 261 |  |  |  |  |  |  |  | 
| 262 |  |  |  |  |  |  | sub _get_contracts { | 
| 263 | 815 |  |  | 815 |  | 1169 | my ( $symbol, $type ) = @_; | 
| 264 | 815 | 100 |  |  |  | 853 | @{ $contracts->{$symbol}{$type} || [] }; | 
|  | 815 |  |  |  |  | 5329 |  | 
| 265 |  |  |  |  |  |  | } | 
| 266 |  |  |  |  |  |  |  | 
| 267 |  |  |  |  |  |  | sub _erase_contracts { | 
| 268 | 140 |  |  | 140 |  | 217 | my ( $symbol, $type ) = @_; | 
| 269 | 140 |  |  |  |  | 410 | delete $contracts->{$symbol}{$type}; | 
| 270 |  |  |  |  |  |  | } | 
| 271 |  |  |  |  |  |  |  | 
| 272 |  |  |  |  |  |  | sub _copy_of { | 
| 273 | 436 |  |  | 436 |  | 422 | return @{ \@_ }; | 
|  | 436 |  |  |  |  | 1650 |  | 
| 274 |  |  |  |  |  |  | } | 
| 275 |  |  |  |  |  |  |  | 
| 276 |  |  |  |  |  |  | sub _symbol_to_package_and_method { | 
| 277 | 71 |  |  | 71 |  | 531 | shift =~ /^(.+)::(.+)$/; | 
| 278 |  |  |  |  |  |  | } | 
| 279 |  |  |  |  |  |  |  | 
| 280 |  |  |  |  |  |  | sub _package_and_method_to_symbol { | 
| 281 | 318 | 100 |  | 318 |  | 1570 | ( $_[1] =~ /::/ ) ? $_[1] : "$_[0]\::$_[1]"; | 
| 282 |  |  |  |  |  |  | } | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  | sub _is_constructor { | 
| 285 | 67 |  |  | 67 |  | 120 | my ( $package, $name ) = @_; | 
| 286 |  |  |  |  |  |  | return | 
| 287 | 67 | 100 |  |  |  | 264 | exists $constructors->{$package} | 
| 288 |  |  |  |  |  |  | ? exists $constructors->{$package}{$name} | 
| 289 |  |  |  |  |  |  | : $name eq 'new'; | 
| 290 |  |  |  |  |  |  | } | 
| 291 |  |  |  |  |  |  |  | 
| 292 |  |  |  |  |  |  | sub _set_constructors { | 
| 293 | 3 |  |  | 3 |  | 9 | my ( $package, @constructors ) = @_; | 
| 294 | 3 |  |  |  |  | 9 | my %lookup = ( map { ; $_ => 1 } @constructors ); | 
|  | 3 |  |  |  |  | 9 |  | 
| 295 |  |  |  |  |  |  | $constructors->{$_} = \%lookup | 
| 296 | 3 |  |  |  |  | 13 | for $package, Class::Inspector->subclasses($package); | 
| 297 |  |  |  |  |  |  | } | 
| 298 |  |  |  |  |  |  |  | 
| 299 |  |  |  |  |  |  | sub _get_constructors { | 
| 300 | 0 |  |  | 0 |  | 0 | my ($package) = @_; | 
| 301 | 0 |  | 0 |  |  | 0 | return $constructors->{$package} || []; | 
| 302 |  |  |  |  |  |  | } | 
| 303 |  |  |  |  |  |  |  | 
| 304 |  |  |  |  |  |  | sub _make_method_wrapper { | 
| 305 | 71 |  |  | 71 |  | 141 | my ($symbol) = @_; | 
| 306 | 71 |  |  |  |  | 217 | my ( $package, $method ) = _symbol_to_package_and_method($symbol); | 
| 307 | 71 |  |  |  |  | 244 | my $parent = _parent_class_of_method( $package, $method ); | 
| 308 | 71 | 50 |  |  |  | 267 | my $parent_symbol = | 
| 309 |  |  |  |  |  |  | defined $parent | 
| 310 |  |  |  |  |  |  | ? _package_and_method_to_symbol( $parent, $method ) | 
| 311 |  |  |  |  |  |  | : undef; | 
| 312 |  |  |  |  |  |  |  | 
| 313 |  |  |  |  |  |  | return sub { | 
| 314 | 128 |  |  | 128 |  | 112979 | my @arguments = @_; | 
| 315 |  |  |  |  |  |  |  | 
| 316 |  |  |  |  |  |  | # | 
| 317 |  |  |  |  |  |  | # do invariants, blame outside sources | 
| 318 |  |  |  |  |  |  | # | 
| 319 | 128 | 100 |  |  |  | 633 | if ( blessed( $_[0] ) ) { | 
| 320 | 54 |  |  |  |  | 118 | foreach ( _get_contracts( $symbol, 'invar' ) ) { | 
| 321 | 15 |  |  |  |  | 33 | my ( $block, $file, $line ) = @$_; | 
| 322 | 15 |  |  |  |  | 22 | my $success = eval { $block->( _copy_of( $arguments[0] ) ) }; | 
|  | 15 |  |  |  |  | 36 |  | 
| 323 | 15 | 50 |  |  |  | 1105 | if ($@) { | 
|  |  | 100 |  |  |  |  |  | 
| 324 | 0 |  |  |  |  | 0 | croak "invariant for $symbol died: $@ " | 
| 325 |  |  |  |  |  |  | . "from $file line $line"; | 
| 326 |  |  |  |  |  |  | } | 
| 327 |  |  |  |  |  |  | elsif ( not $success ) { | 
| 328 | 1 |  |  |  |  | 17 | croak "invariant for $symbol failed due to " | 
| 329 |  |  |  |  |  |  | . "an outside source tampering with the object " | 
| 330 |  |  |  |  |  |  | . "from $file line $line"; | 
| 331 |  |  |  |  |  |  | } | 
| 332 |  |  |  |  |  |  | } | 
| 333 |  |  |  |  |  |  | } | 
| 334 |  |  |  |  |  |  |  | 
| 335 |  |  |  |  |  |  | # | 
| 336 |  |  |  |  |  |  | # do dependent contracts | 
| 337 |  |  |  |  |  |  | # | 
| 338 | 127 |  |  |  |  | 351 | _erase_contracts( $symbol, 'temp-post' ); | 
| 339 | 127 |  |  |  |  | 253 | foreach ( _get_contracts( $symbol, 'dep' ) ) { | 
| 340 | 19 |  |  |  |  | 33 | my ( $block, $file, $line ) = @$_; | 
| 341 | 19 |  |  |  |  | 28 | my $postcondition = eval { $block->( _copy_of(@arguments) ) }; | 
|  | 19 |  |  |  |  | 47 |  | 
| 342 | 19 | 50 |  |  |  | 1156 | if ($@) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 343 | 0 |  |  |  |  | 0 | croak "dependent contract for $symbol died: $@ " | 
| 344 |  |  |  |  |  |  | . "from $file line $line"; | 
| 345 |  |  |  |  |  |  | } | 
| 346 |  |  |  |  |  |  | elsif ( not defined $postcondition ) { | 
| 347 | 3 |  |  |  |  | 13 | return; | 
| 348 |  |  |  |  |  |  | } | 
| 349 |  |  |  |  |  |  | elsif ( ref $postcondition ne 'CODE' ) { | 
| 350 | 0 |  |  |  |  | 0 | croak | 
| 351 |  |  |  |  |  |  | "dependent contract for $symbol did not return either a " | 
| 352 |  |  |  |  |  |  | . "subroutine reference or undefine at $file line $line"; | 
| 353 |  |  |  |  |  |  | } | 
| 354 |  |  |  |  |  |  | else { | 
| 355 | 16 |  |  |  |  | 58 | _add_contract( $symbol, 'temp-post', | 
| 356 |  |  |  |  |  |  | [ $postcondition, $file, $line ], $package ); | 
| 357 |  |  |  |  |  |  | } | 
| 358 |  |  |  |  |  |  | } | 
| 359 |  |  |  |  |  |  |  | 
| 360 |  |  |  |  |  |  | # | 
| 361 |  |  |  |  |  |  | # do preconditions | 
| 362 |  |  |  |  |  |  | # | 
| 363 | 124 |  |  |  |  | 332 | foreach ( _get_contracts( $symbol, 'pre' ) ) { | 
| 364 | 79 |  |  |  |  | 147 | my ( $block, $file, $line ) = @$_; | 
| 365 | 79 |  |  |  |  | 100 | my $success = eval { $block->( _copy_of(@arguments) ) }; | 
|  | 79 |  |  |  |  | 182 |  | 
| 366 | 79 | 50 |  |  |  | 1623 | if ($@) { | 
|  |  | 100 |  |  |  |  |  | 
| 367 | 0 |  |  |  |  | 0 | croak "precondition for $symbol died: $@ " | 
| 368 |  |  |  |  |  |  | . "from $file line $line"; | 
| 369 |  |  |  |  |  |  | } | 
| 370 |  |  |  |  |  |  | elsif ( not $success ) { | 
| 371 | 28 | 100 | 66 |  |  | 127 | if (defined $parent | 
| 372 |  |  |  |  |  |  | and my @parent_contracts = _get_contracts( | 
| 373 |  |  |  |  |  |  | _package_and_method_to_symbol( $parent, $method ), | 
| 374 |  |  |  |  |  |  | 'pre' | 
| 375 |  |  |  |  |  |  | ) | 
| 376 |  |  |  |  |  |  | ) | 
| 377 |  |  |  |  |  |  | { | 
| 378 | 8 |  |  |  |  | 19 | foreach (@parent_contracts) { | 
| 379 | 8 |  |  |  |  | 18 | my ( $parent_block, $parent_file, $parent_line ) | 
| 380 |  |  |  |  |  |  | = @$_; | 
| 381 | 8 | 100 |  |  |  | 12 | if ( eval { $parent_block->( _copy_of(@arguments) ) } | 
|  | 8 |  |  |  |  | 19 |  | 
| 382 |  |  |  |  |  |  | ) | 
| 383 |  |  |  |  |  |  | { | 
| 384 | 4 |  |  |  |  | 108 | croak "precondition for $symbol failed " | 
| 385 |  |  |  |  |  |  | . "from $parent_file line $parent_line (the parent) " | 
| 386 |  |  |  |  |  |  | . "and file $file line $line (the child) -- " | 
| 387 |  |  |  |  |  |  | . "check hierarchy between $parent and $package"; | 
| 388 |  |  |  |  |  |  | } | 
| 389 |  |  |  |  |  |  | else { | 
| 390 | 4 |  |  |  |  | 90 | croak "precondition for $symbol failed " | 
| 391 |  |  |  |  |  |  | . "due to client input " | 
| 392 |  |  |  |  |  |  | . "from file $file line $line"; | 
| 393 |  |  |  |  |  |  | } | 
| 394 |  |  |  |  |  |  | } | 
| 395 |  |  |  |  |  |  | } | 
| 396 |  |  |  |  |  |  | else { | 
| 397 | 20 |  |  |  |  | 362 | croak "precondition for $symbol failed " | 
| 398 |  |  |  |  |  |  | . "from $file line $line"; | 
| 399 |  |  |  |  |  |  | } | 
| 400 |  |  |  |  |  |  | } | 
| 401 |  |  |  |  |  |  | } | 
| 402 |  |  |  |  |  |  |  | 
| 403 |  |  |  |  |  |  | # | 
| 404 |  |  |  |  |  |  | # we need to call the method/function in the same context in which the | 
| 405 |  |  |  |  |  |  | # contract was called | 
| 406 |  |  |  |  |  |  | # | 
| 407 | 96 |  |  |  |  | 278 | my $implementation = _get_implementation($symbol); | 
| 408 |  |  |  |  |  |  | my @result         = ( not defined wantarray ) | 
| 409 | 96 | 100 |  |  |  | 333 | ? do { $implementation->( _copy_of(@arguments) ) } | 
|  | 81 | 100 |  |  |  | 172 |  | 
| 410 |  |  |  |  |  |  | : wantarray ? ( $implementation->( _copy_of(@arguments) ) ) | 
| 411 |  |  |  |  |  |  | : ( scalar $implementation->( _copy_of(@arguments) ) ); | 
| 412 |  |  |  |  |  |  |  | 
| 413 |  |  |  |  |  |  | # | 
| 414 |  |  |  |  |  |  | # do postconditions | 
| 415 |  |  |  |  |  |  | # | 
| 416 |  |  |  |  |  |  | { | 
| 417 | 19 |  |  | 19 |  | 141 | no strict 'refs'; | 
|  | 19 |  |  |  |  | 35 |  | 
|  | 19 |  |  |  |  | 2203 |  | 
|  | 96 |  |  |  |  | 1855 |  | 
| 418 | 19 |  |  | 19 |  | 117 | no warnings 'redefine'; | 
|  | 19 |  |  |  |  | 206 |  | 
|  | 19 |  |  |  |  | 30994 |  | 
| 419 | 96 | 100 |  | 74 |  | 493 | local *_real_result = sub { wantarray ? @result : $result[0] }; | 
|  | 74 |  |  |  |  | 303 |  | 
| 420 |  |  |  |  |  |  |  | 
| 421 | 96 |  |  |  |  | 267 | foreach ( | 
| 422 |  |  |  |  |  |  | _get_contracts( $symbol, 'post' ), | 
| 423 |  |  |  |  |  |  | _get_contracts( $symbol, 'temp-post' ) | 
| 424 |  |  |  |  |  |  | ) | 
| 425 |  |  |  |  |  |  | { | 
| 426 | 66 |  |  |  |  | 120 | my ( $child_block, $child_file, $child_line ) = @$_; | 
| 427 |  |  |  |  |  |  |  | 
| 428 |  |  |  |  |  |  | my $child_success | 
| 429 | 66 |  |  |  |  | 87 | = eval { $child_block->( _copy_of(@arguments) ) }; | 
|  | 66 |  |  |  |  | 205 |  | 
| 430 | 66 | 50 | 66 |  |  | 5370 | if ($@) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 431 | 0 |  |  |  |  | 0 | croak "postcondition for $symbol died: $@ " | 
| 432 |  |  |  |  |  |  | . "from $child_file line $child_line"; | 
| 433 |  |  |  |  |  |  | } | 
| 434 |  |  |  |  |  |  | elsif ( | 
| 435 |  |  |  |  |  |  | defined $parent | 
| 436 |  |  |  |  |  |  | and my @parent_contracts = ( | 
| 437 |  |  |  |  |  |  | _get_contracts( $parent_symbol, 'post' ), | 
| 438 |  |  |  |  |  |  | _get_contracts( $parent_symbol, 'temp-post' ) | 
| 439 |  |  |  |  |  |  | ) | 
| 440 |  |  |  |  |  |  | ) | 
| 441 |  |  |  |  |  |  | { | 
| 442 | 12 |  |  |  |  | 22 | foreach (@parent_contracts) { | 
| 443 | 12 |  |  |  |  | 27 | my ( $parent_block, $parent_file, $parent_line ) | 
| 444 |  |  |  |  |  |  | = @$_; | 
| 445 |  |  |  |  |  |  | my $parent_success | 
| 446 | 12 |  |  |  |  | 19 | = eval { $parent_block->( _copy_of(@arguments) ) }; | 
|  | 12 |  |  |  |  | 22 |  | 
| 447 | 12 | 50 | 100 |  |  | 153 | if ($@) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 448 | 0 |  |  |  |  | 0 | croak "postcondition for $symbol died: $@ " | 
| 449 |  |  |  |  |  |  | . "from $child_file line $child_line"; | 
| 450 |  |  |  |  |  |  | } | 
| 451 |  |  |  |  |  |  | elsif ( $child_success and not $parent_success ) { | 
| 452 | 2 |  |  |  |  | 58 | croak "postcondition for $symbol failed " | 
| 453 |  |  |  |  |  |  | . "at $parent_file line $parent_line (the parent) " | 
| 454 |  |  |  |  |  |  | . "and file $child_file line $child_line (the child) -- " | 
| 455 |  |  |  |  |  |  | . "check hierarchy between $parent and $package"; | 
| 456 |  |  |  |  |  |  | } | 
| 457 |  |  |  |  |  |  | elsif ( not $child_success ) { | 
| 458 | 5 |  |  |  |  | 110 | croak | 
| 459 |  |  |  |  |  |  | "postcondition for $symbol failed since its " | 
| 460 |  |  |  |  |  |  | . "implementation didn't adhere to the contract " | 
| 461 |  |  |  |  |  |  | . "from file $child_file line $child_line"; | 
| 462 |  |  |  |  |  |  | } | 
| 463 |  |  |  |  |  |  | } | 
| 464 |  |  |  |  |  |  | } | 
| 465 |  |  |  |  |  |  | elsif ( not $child_success ) { | 
| 466 | 22 |  |  |  |  | 1015 | croak "postcondition for $symbol failed " | 
| 467 |  |  |  |  |  |  | . "from $child_file line $child_line"; | 
| 468 |  |  |  |  |  |  | } | 
| 469 |  |  |  |  |  |  | } | 
| 470 |  |  |  |  |  |  | } | 
| 471 |  |  |  |  |  |  |  | 
| 472 |  |  |  |  |  |  | # | 
| 473 |  |  |  |  |  |  | # do invariants, blame method | 
| 474 |  |  |  |  |  |  | # | 
| 475 | 67 |  |  |  |  | 225 | my $is_constructor = _is_constructor( $package, $method ); | 
| 476 | 67 | 100 | 100 |  |  | 452 | if ( blessed( $_[0] ) or $is_constructor ) { | 
| 477 | 40 |  |  |  |  | 87 | foreach ( _get_contracts( $symbol, 'invar' ) ) { | 
| 478 | 28 |  |  |  |  | 57 | my ( $block, $file, $line ) = @$_; | 
| 479 | 28 |  |  |  |  | 41 | my $success = eval { | 
| 480 | 28 | 100 |  |  |  | 73 | $block->( | 
| 481 |  |  |  |  |  |  | _copy_of( | 
| 482 |  |  |  |  |  |  | $is_constructor ? $result[0] : $arguments[0] | 
| 483 |  |  |  |  |  |  | ) | 
| 484 |  |  |  |  |  |  | ); | 
| 485 |  |  |  |  |  |  | }; | 
| 486 | 28 | 50 |  |  |  | 2347 | if ($@) { | 
|  |  | 100 |  |  |  |  |  | 
| 487 | 0 |  |  |  |  | 0 | croak "invariant for $symbol died: $@ " | 
| 488 |  |  |  |  |  |  | . "from $file line $line"; | 
| 489 |  |  |  |  |  |  | } | 
| 490 |  |  |  |  |  |  | elsif ( not $success ) { | 
| 491 | 1 |  |  |  |  | 33 | croak "invariant for $symbol failed due to " | 
| 492 |  |  |  |  |  |  | . "the method's implementation being broken " | 
| 493 |  |  |  |  |  |  | . "from $file line $line"; | 
| 494 |  |  |  |  |  |  | } | 
| 495 |  |  |  |  |  |  | } | 
| 496 |  |  |  |  |  |  | } | 
| 497 |  |  |  |  |  |  |  | 
| 498 | 66 | 100 |  |  |  | 408 | wantarray ? @result : $result[0]; | 
| 499 | 71 |  |  |  |  | 2382 | }; | 
| 500 |  |  |  |  |  |  | } | 
| 501 |  |  |  |  |  |  |  | 
| 502 |  |  |  |  |  |  | =head1 FUNCTIONS | 
| 503 |  |  |  |  |  |  |  | 
| 504 |  |  |  |  |  |  | =head2 precondition NAME, BLOCK | 
| 505 |  |  |  |  |  |  |  | 
| 506 |  |  |  |  |  |  | Specify that the method NAME must meet the precondition as specified in BLOCK. | 
| 507 |  |  |  |  |  |  |  | 
| 508 |  |  |  |  |  |  | In BLOCK, the variable C<@_> will be the argument list of the method.  (The | 
| 509 |  |  |  |  |  |  | first item of C<@_> will be the class name or object, as usual.) | 
| 510 |  |  |  |  |  |  |  | 
| 511 |  |  |  |  |  |  | For example, to specify a precondition on a method to ensure that the first | 
| 512 |  |  |  |  |  |  | argument given is greater than zero: | 
| 513 |  |  |  |  |  |  |  | 
| 514 |  |  |  |  |  |  | precondition foo => sub { | 
| 515 |  |  |  |  |  |  | my ( $self, $value ) = @_; | 
| 516 |  |  |  |  |  |  | return ( $value >= 0 ); | 
| 517 |  |  |  |  |  |  | }; | 
| 518 |  |  |  |  |  |  | sub foo { | 
| 519 |  |  |  |  |  |  | my ( $self, $value ) = @_; | 
| 520 |  |  |  |  |  |  | ... | 
| 521 |  |  |  |  |  |  | } | 
| 522 |  |  |  |  |  |  |  | 
| 523 |  |  |  |  |  |  | With methods, if the precondition fails (returns false), preconditions for the | 
| 524 |  |  |  |  |  |  | parent class will be checked. If the preconditions for both the child's method | 
| 525 |  |  |  |  |  |  | and the parent's method fail, the input to the method must have been invalid. If | 
| 526 |  |  |  |  |  |  | the precondition for the parent passes, the hierarchy between the class and the | 
| 527 |  |  |  |  |  |  | parent class is incorrect because, to fulfill the Liskov-Wing principal of | 
| 528 |  |  |  |  |  |  | substitutability, the subclass' method should accept that the superclass' does, | 
| 529 |  |  |  |  |  |  | and optionally more. Note that only the relationships between child and parent | 
| 530 |  |  |  |  |  |  | classes are checked -- this module won't traverse the complete ancestry of | 
| 531 |  |  |  |  |  |  | a class. | 
| 532 |  |  |  |  |  |  |  | 
| 533 |  |  |  |  |  |  | You can use this keyword multiple times to declare multiple preconditions on | 
| 534 |  |  |  |  |  |  | the given method. | 
| 535 |  |  |  |  |  |  |  | 
| 536 |  |  |  |  |  |  | =cut | 
| 537 |  |  |  |  |  |  |  | 
| 538 |  |  |  |  |  |  | =head2 precondition VARIABLE, BLOCK | 
| 539 |  |  |  |  |  |  |  | 
| 540 |  |  |  |  |  |  | Specify that, when called, the subroutine reference pointed to by the lvalue | 
| 541 |  |  |  |  |  |  | VARIABLE must meet the precondition as specified in BLOCK. | 
| 542 |  |  |  |  |  |  |  | 
| 543 |  |  |  |  |  |  | In BLOCK, the variable C<@_> will be the argument list of the subroutine. | 
| 544 |  |  |  |  |  |  |  | 
| 545 |  |  |  |  |  |  | There are times when you will have a function or method that accepts another | 
| 546 |  |  |  |  |  |  | function as an argument. Say that you have a function C that accepts | 
| 547 |  |  |  |  |  |  | another function, C, as its argument. However, the argument given to C | 
| 548 |  |  |  |  |  |  | must be greater than zero: | 
| 549 |  |  |  |  |  |  |  | 
| 550 |  |  |  |  |  |  | sub g { | 
| 551 |  |  |  |  |  |  | my ($f) = @_; | 
| 552 |  |  |  |  |  |  | precondition $f => sub { | 
| 553 |  |  |  |  |  |  | my ($value) = @_; | 
| 554 |  |  |  |  |  |  | return ( $value >= 0 ); | 
| 555 |  |  |  |  |  |  | }; | 
| 556 |  |  |  |  |  |  | $f->(15); # will pass | 
| 557 |  |  |  |  |  |  | $f->(-3); # will fail | 
| 558 |  |  |  |  |  |  | } | 
| 559 |  |  |  |  |  |  |  | 
| 560 |  |  |  |  |  |  | If called in void context this function will modify VARIABLE to point to a new | 
| 561 |  |  |  |  |  |  | subroutine reference with the precondition. If called in scalar | 
| 562 |  |  |  |  |  |  | context, this function will return a new function with the attached | 
| 563 |  |  |  |  |  |  | precondition. | 
| 564 |  |  |  |  |  |  |  | 
| 565 |  |  |  |  |  |  | You can use this keyword multiple times to declare multiple preconditions on | 
| 566 |  |  |  |  |  |  | the given function. | 
| 567 |  |  |  |  |  |  |  | 
| 568 |  |  |  |  |  |  | =cut | 
| 569 |  |  |  |  |  |  |  | 
| 570 |  |  |  |  |  |  | sub precondition { | 
| 571 | 45 |  |  | 45 | 1 | 23743 | my ( $glob, $block ) = @_; | 
| 572 | 45 |  |  |  |  | 193 | my ( $package, $file, $line ) = caller(); | 
| 573 | 45 |  |  |  |  | 1496 | _check_arguments(@_); | 
| 574 |  |  |  |  |  |  |  | 
| 575 | 45 | 100 | 33 |  |  | 215 | if ( not ref $glob ) { | 
|  |  | 50 |  |  |  |  |  | 
| 576 | 29 |  |  |  |  | 124 | _add_contract_for_hierarchy( $package, $glob, | 
| 577 |  |  |  |  |  |  | pre => [ $block, $file, $line ] ); | 
| 578 |  |  |  |  |  |  | } | 
| 579 |  |  |  |  |  |  |  | 
| 580 |  |  |  |  |  |  | elsif ( defined ref $glob and ref $glob eq 'CODE' ) { | 
| 581 | 16 |  |  |  |  | 40 | my $original = $glob; | 
| 582 |  |  |  |  |  |  | my $wrapped = sub { | 
| 583 | 20 |  |  | 20 |  | 4658 | my @arguments = @_; | 
| 584 | 20 |  |  |  |  | 55 | my $success = eval { $block->( _copy_of(@arguments) ) }; | 
|  | 20 |  |  |  |  | 45 |  | 
| 585 | 20 | 50 |  |  |  | 125 | if ($@) { | 
|  |  | 100 |  |  |  |  |  | 
| 586 | 0 |  |  |  |  | 0 | croak "precondition for function died: $@"; | 
| 587 |  |  |  |  |  |  | } | 
| 588 |  |  |  |  |  |  | elsif ( not $success ) { | 
| 589 | 7 |  |  |  |  | 102 | croak | 
| 590 |  |  |  |  |  |  | "precondition for function failed at $file line $line\n"; | 
| 591 |  |  |  |  |  |  | } | 
| 592 | 13 |  |  |  |  | 24 | $original->( &_copy_of(@arguments) ); | 
| 593 | 16 |  |  |  |  | 85 | }; | 
| 594 | 16 | 100 |  |  |  | 42 | if ( defined wantarray ) { | 
| 595 | 1 |  |  |  |  | 4 | return $wrapped; | 
| 596 |  |  |  |  |  |  | } | 
| 597 |  |  |  |  |  |  | else { | 
| 598 | 15 |  |  |  |  | 46 | $_[0] = $wrapped; | 
| 599 |  |  |  |  |  |  | } | 
| 600 |  |  |  |  |  |  | } | 
| 601 |  |  |  |  |  |  | else { | 
| 602 | 0 |  |  |  |  | 0 | croak "first argument to precondition() " | 
| 603 |  |  |  |  |  |  | . "was not a method name or code reference"; | 
| 604 |  |  |  |  |  |  | } | 
| 605 |  |  |  |  |  |  | } | 
| 606 |  |  |  |  |  |  |  | 
| 607 |  |  |  |  |  |  | =head2 postcondition NAME, BLOCK | 
| 608 |  |  |  |  |  |  |  | 
| 609 |  |  |  |  |  |  | Specify that the method NAME must meet the postcondition as specified in BLOCK. | 
| 610 |  |  |  |  |  |  |  | 
| 611 |  |  |  |  |  |  | In BLOCK, the variable C<@_> will be the argument list of the method.  The | 
| 612 |  |  |  |  |  |  | function C may be used to retrieve the return values of the method. If | 
| 613 |  |  |  |  |  |  | the method returns a list, calling C in array context will return all | 
| 614 |  |  |  |  |  |  | of return values, and calling C in scalar context will return only the | 
| 615 |  |  |  |  |  |  | first item of that list. If the method returns a scalar, C called in | 
| 616 |  |  |  |  |  |  | scalar context will be that scalar, and C in array context will return | 
| 617 |  |  |  |  |  |  | a list with one element. | 
| 618 |  |  |  |  |  |  |  | 
| 619 |  |  |  |  |  |  | For example, to specify a postcondition on a method to ensure that the method | 
| 620 |  |  |  |  |  |  | returns a number less than zero, BLOCK would check the | 
| 621 |  |  |  |  |  |  |  | 
| 622 |  |  |  |  |  |  | sub foo { | 
| 623 |  |  |  |  |  |  | my ( $self, $value ) = @_; | 
| 624 |  |  |  |  |  |  | ... | 
| 625 |  |  |  |  |  |  | } | 
| 626 |  |  |  |  |  |  | postcondition foo => sub { | 
| 627 |  |  |  |  |  |  | return ( result >= 0 ); | 
| 628 |  |  |  |  |  |  | }; | 
| 629 |  |  |  |  |  |  |  | 
| 630 |  |  |  |  |  |  | With methods, postconditions for the parent class will be checked if they | 
| 631 |  |  |  |  |  |  | exist. If the postcondition for the child's method fails, the blame lies with | 
| 632 |  |  |  |  |  |  | the child method's implementation since it is not adhering to its contract. If | 
| 633 |  |  |  |  |  |  | the postcondition for the child method passes, but the postcondition for the | 
| 634 |  |  |  |  |  |  | parent's fails, the problem lies with the hierarchy betweeen the classes. Note | 
| 635 |  |  |  |  |  |  | again that only the relationships between child and parent classes are checked | 
| 636 |  |  |  |  |  |  | -- this module won't traverse the complete ancestry of a class. | 
| 637 |  |  |  |  |  |  |  | 
| 638 |  |  |  |  |  |  | You can use this keyword multiple times to declare multiple postconditions on | 
| 639 |  |  |  |  |  |  | the given method. | 
| 640 |  |  |  |  |  |  |  | 
| 641 |  |  |  |  |  |  | =head2 postcondition VARIABLE, BLOCK | 
| 642 |  |  |  |  |  |  |  | 
| 643 |  |  |  |  |  |  | Specify that, when called, the subroutine reference pointed to by the lvalue | 
| 644 |  |  |  |  |  |  | VARIABLE must meet the postcondition as specified in BLOCK. | 
| 645 |  |  |  |  |  |  |  | 
| 646 |  |  |  |  |  |  | In BLOCK, the varable C<@_> and function C are available and may be | 
| 647 |  |  |  |  |  |  | used in the same ways as described in the previous usage of C. | 
| 648 |  |  |  |  |  |  |  | 
| 649 |  |  |  |  |  |  | Say that you have a function C that accepts another function, C as its | 
| 650 |  |  |  |  |  |  | argument. C, however, must return a number that is divisible by two. This | 
| 651 |  |  |  |  |  |  | can be expressed as: | 
| 652 |  |  |  |  |  |  |  | 
| 653 |  |  |  |  |  |  | sub g { | 
| 654 |  |  |  |  |  |  | my ($f) = @_; | 
| 655 |  |  |  |  |  |  | postcondition $f => sub { | 
| 656 |  |  |  |  |  |  | return ! ( result % 2 ); | 
| 657 |  |  |  |  |  |  | }; | 
| 658 |  |  |  |  |  |  | ... | 
| 659 |  |  |  |  |  |  | } | 
| 660 |  |  |  |  |  |  |  | 
| 661 |  |  |  |  |  |  | If called in void context this function will modify VARIABLE to point to a new | 
| 662 |  |  |  |  |  |  | subroutine reference with the postcondition. If called in scalar | 
| 663 |  |  |  |  |  |  | context, this function will return a new function with the attached | 
| 664 |  |  |  |  |  |  | postcondition. | 
| 665 |  |  |  |  |  |  |  | 
| 666 |  |  |  |  |  |  | You can use this keyword multiple times to declare multiple postconditions on | 
| 667 |  |  |  |  |  |  | the given function. | 
| 668 |  |  |  |  |  |  |  | 
| 669 |  |  |  |  |  |  | =cut | 
| 670 |  |  |  |  |  |  |  | 
| 671 |  |  |  |  |  |  | sub postcondition { | 
| 672 | 36 |  |  | 36 | 1 | 15162 | my ( $glob, $block ) = @_; | 
| 673 | 36 |  |  |  |  | 173 | my ( $package, $file, $line ) = caller(); | 
| 674 | 36 |  |  |  |  | 985 | _check_arguments(@_); | 
| 675 |  |  |  |  |  |  |  | 
| 676 | 36 | 100 | 33 |  |  | 405 | if ( not ref $glob ) { | 
|  |  | 50 |  |  |  |  |  | 
| 677 | 21 |  |  |  |  | 89 | _add_contract_for_hierarchy( $package, $glob, | 
| 678 |  |  |  |  |  |  | post => [ $block, $file, $line ] ); | 
| 679 |  |  |  |  |  |  | } | 
| 680 |  |  |  |  |  |  |  | 
| 681 |  |  |  |  |  |  | elsif ( defined ref $glob and ref $glob eq 'CODE' ) { | 
| 682 | 15 |  |  |  |  | 24 | my $implementation = $glob; | 
| 683 |  |  |  |  |  |  | my $wrapped = sub { | 
| 684 | 21 |  |  | 21 |  | 4678 | my @arguments = @_; | 
| 685 |  |  |  |  |  |  |  | 
| 686 |  |  |  |  |  |  | my @result = ( not defined wantarray ) | 
| 687 | 21 | 100 |  |  |  | 78 | ? do { $implementation->( _copy_of(@arguments) ) } | 
|  | 14 | 100 |  |  |  | 35 |  | 
| 688 |  |  |  |  |  |  | : wantarray ? ( $implementation->( _copy_of(@arguments) ) ) | 
| 689 |  |  |  |  |  |  | : ( scalar $implementation->( _copy_of(@arguments) ) ); | 
| 690 |  |  |  |  |  |  |  | 
| 691 | 19 |  |  |  |  | 886 | my $success; | 
| 692 |  |  |  |  |  |  | { | 
| 693 | 19 |  |  | 19 |  | 135 | no strict 'refs'; | 
|  | 19 |  |  |  |  | 46 |  | 
|  | 19 |  |  |  |  | 681 |  | 
|  | 19 |  |  |  |  | 24 |  | 
| 694 | 19 |  |  | 19 |  | 93 | no warnings 'redefine'; | 
|  | 19 |  |  |  |  | 35 |  | 
|  | 19 |  |  |  |  | 11643 |  | 
| 695 |  |  |  |  |  |  | local *_real_result | 
| 696 | 19 | 100 |  |  |  | 87 | = sub { wantarray ? @result : $result[0] }; | 
|  | 28 |  |  |  |  | 163 |  | 
| 697 |  |  |  |  |  |  |  | 
| 698 | 19 |  |  |  |  | 29 | $success = eval { $block->( _copy_of(@arguments) ) }; | 
|  | 19 |  |  |  |  | 37 |  | 
| 699 |  |  |  |  |  |  |  | 
| 700 | 19 | 50 |  |  |  | 7034 | if ($@) { | 
|  |  | 100 |  |  |  |  |  | 
| 701 | 0 |  |  |  |  | 0 | croak "postcondition for function died: $@"; | 
| 702 |  |  |  |  |  |  | } | 
| 703 |  |  |  |  |  |  | elsif ( not $success ) { | 
| 704 | 7 |  |  |  |  | 111 | croak | 
| 705 |  |  |  |  |  |  | "postcondition for function failed at $file line $line"; | 
| 706 |  |  |  |  |  |  | } | 
| 707 |  |  |  |  |  |  | else { | 
| 708 | 12 |  |  |  |  | 43 | goto &_real_result; | 
| 709 |  |  |  |  |  |  | } | 
| 710 |  |  |  |  |  |  | } | 
| 711 | 15 |  |  |  |  | 73 | }; | 
| 712 | 15 | 100 |  |  |  | 33 | if ( defined wantarray ) { | 
| 713 | 3 |  |  |  |  | 12 | return $wrapped; | 
| 714 |  |  |  |  |  |  | } | 
| 715 |  |  |  |  |  |  | else { | 
| 716 | 12 |  |  |  |  | 35 | $_[0] = $wrapped; | 
| 717 |  |  |  |  |  |  | } | 
| 718 |  |  |  |  |  |  | } | 
| 719 |  |  |  |  |  |  | else { | 
| 720 | 0 |  |  |  |  | 0 | croak "first argument to precondition() " | 
| 721 |  |  |  |  |  |  | . "was not a method name or code reference"; | 
| 722 |  |  |  |  |  |  | } | 
| 723 |  |  |  |  |  |  | } | 
| 724 |  |  |  |  |  |  |  | 
| 725 |  |  |  |  |  |  | =head2 dependent NAME, BLOCK | 
| 726 |  |  |  |  |  |  |  | 
| 727 |  |  |  |  |  |  | Specify that the method NAME will use the subroutine reference returned by BLOCK | 
| 728 |  |  |  |  |  |  | as a postcondition. If BLOCK returns undefined, no postcondition will be added. | 
| 729 |  |  |  |  |  |  | In some cases, the postcondition returned will I on the input provided, | 
| 730 |  |  |  |  |  |  | hence these are referred to as I. However, since the | 
| 731 |  |  |  |  |  |  | arguments to the method are given in the postcondition, dependent contracts will | 
| 732 |  |  |  |  |  |  | be used typically to compare old and new values. | 
| 733 |  |  |  |  |  |  |  | 
| 734 |  |  |  |  |  |  | BLOCK is run at the same time as preconditions, thus the C<@_> variable works | 
| 735 |  |  |  |  |  |  | in the same manner as in preconditions. However, the subroutine reference that | 
| 736 |  |  |  |  |  |  | BLOCK returns will be invoked as a postcondition, thus it may the C | 
| 737 |  |  |  |  |  |  | function in addition to C<@_>. | 
| 738 |  |  |  |  |  |  |  | 
| 739 |  |  |  |  |  |  | You'll probably use these, along with closure, to check the old copies of | 
| 740 |  |  |  |  |  |  | values. See the example in L. | 
| 741 |  |  |  |  |  |  |  | 
| 742 |  |  |  |  |  |  | You can use this keyword multiple times to declare multiple dependent contracts | 
| 743 |  |  |  |  |  |  | on the given method. | 
| 744 |  |  |  |  |  |  |  | 
| 745 |  |  |  |  |  |  | =head2 dependent VARIABLE, BLOCK | 
| 746 |  |  |  |  |  |  |  | 
| 747 |  |  |  |  |  |  | Specify that the subroutine reference pointed to by the lvalue VARIABLE will use | 
| 748 |  |  |  |  |  |  | the subroutine reference returned by BLOCK as a postcondition. If BLOCK returns | 
| 749 |  |  |  |  |  |  | undefined, no postcondition will be added. | 
| 750 |  |  |  |  |  |  |  | 
| 751 |  |  |  |  |  |  | Identical to the previous usage, BLOCK is run at the same time as | 
| 752 |  |  |  |  |  |  | preconditions, thus the C<@_> variable works in the same manner as in | 
| 753 |  |  |  |  |  |  | preconditions. However, the subroutine reference that BLOCK returns will be | 
| 754 |  |  |  |  |  |  | invoked as a postcondition, thus it may the C function in addition to | 
| 755 |  |  |  |  |  |  | C<@_>. | 
| 756 |  |  |  |  |  |  |  | 
| 757 |  |  |  |  |  |  | Say that you have a function C that accepts another function, C as its | 
| 758 |  |  |  |  |  |  | argument. You want to make sure that C, as a side effect, adds to the | 
| 759 |  |  |  |  |  |  | global variable C<$count>: | 
| 760 |  |  |  |  |  |  |  | 
| 761 |  |  |  |  |  |  | my $count = 0; | 
| 762 |  |  |  |  |  |  | ... | 
| 763 |  |  |  |  |  |  |  | 
| 764 |  |  |  |  |  |  | sub g { | 
| 765 |  |  |  |  |  |  | my ($f) = @_; | 
| 766 |  |  |  |  |  |  | dependent $f => sub { | 
| 767 |  |  |  |  |  |  | my $old_count = $count; | 
| 768 |  |  |  |  |  |  | return sub { $count > $old_count }; | 
| 769 |  |  |  |  |  |  | }; | 
| 770 |  |  |  |  |  |  | ... | 
| 771 |  |  |  |  |  |  | } | 
| 772 |  |  |  |  |  |  |  | 
| 773 |  |  |  |  |  |  | You can use this keyword multiple times to declare multiple dependent contracts | 
| 774 |  |  |  |  |  |  | on the given function. | 
| 775 |  |  |  |  |  |  |  | 
| 776 |  |  |  |  |  |  | =cut | 
| 777 |  |  |  |  |  |  |  | 
| 778 |  |  |  |  |  |  | sub dependent { | 
| 779 | 18 |  |  | 18 | 1 | 4948 | my ( $glob, $block ) = @_; | 
| 780 | 18 |  |  |  |  | 67 | my ( $package, $file, $line ) = caller(); | 
| 781 | 18 |  |  |  |  | 484 | _check_arguments(@_); | 
| 782 |  |  |  |  |  |  |  | 
| 783 | 18 | 100 | 33 |  |  | 81 | if ( not ref $glob ) { | 
|  |  | 50 |  |  |  |  |  | 
| 784 | 9 |  |  |  |  | 39 | _add_contract_for_hierarchy( $package, $glob, | 
| 785 |  |  |  |  |  |  | dep => [ $block, $file, $line ] ); | 
| 786 |  |  |  |  |  |  | } | 
| 787 |  |  |  |  |  |  |  | 
| 788 |  |  |  |  |  |  | elsif ( defined ref $glob and ref $glob eq 'CODE' ) { | 
| 789 | 9 |  |  |  |  | 20 | my $implementation = $glob; | 
| 790 |  |  |  |  |  |  | my $wrapped = sub { | 
| 791 | 16 |  |  | 16 |  | 2531 | my @arguments = @_; | 
| 792 |  |  |  |  |  |  |  | 
| 793 | 16 |  |  |  |  | 20 | my $postcondition = eval { $block->( _copy_of(@arguments) ) }; | 
|  | 16 |  |  |  |  | 27 |  | 
| 794 | 16 | 50 |  |  |  | 692 | if ($@) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 795 | 0 |  |  |  |  | 0 | croak "dependent contract died: $@ " . "at $file line $line"; | 
| 796 |  |  |  |  |  |  | } | 
| 797 |  |  |  |  |  |  | elsif ( not defined $postcondition ) { | 
| 798 | 3 |  |  |  |  | 20 | return; | 
| 799 |  |  |  |  |  |  | } | 
| 800 |  |  |  |  |  |  | elsif ( ref $postcondition ne 'CODE' ) { | 
| 801 | 0 |  |  |  |  | 0 | croak "dependent contract did not return either a " | 
| 802 |  |  |  |  |  |  | . "subroutine reference or undefine from $file line $line"; | 
| 803 |  |  |  |  |  |  | } | 
| 804 |  |  |  |  |  |  |  | 
| 805 |  |  |  |  |  |  | my @result = ( not defined wantarray ) | 
| 806 | 13 | 50 |  |  |  | 30 | ? do { $implementation->( _copy_of(@arguments) ) } | 
|  | 9 | 100 |  |  |  | 13 |  | 
| 807 |  |  |  |  |  |  | : wantarray ? ( $implementation->( _copy_of(@arguments) ) ) | 
| 808 |  |  |  |  |  |  | : ( scalar $implementation->( _copy_of(@arguments) ) ); | 
| 809 |  |  |  |  |  |  |  | 
| 810 | 11 |  |  |  |  | 33 | my $success; | 
| 811 |  |  |  |  |  |  | { | 
| 812 | 19 |  |  | 19 |  | 111 | no strict 'refs'; | 
|  | 19 |  |  |  |  | 37 |  | 
|  | 19 |  |  |  |  | 815 |  | 
|  | 11 |  |  |  |  | 11 |  | 
| 813 | 19 |  |  | 19 |  | 97 | no warnings 'redefine'; | 
|  | 19 |  |  |  |  | 36 |  | 
|  | 19 |  |  |  |  | 17302 |  | 
| 814 |  |  |  |  |  |  | local *_real_result | 
| 815 | 11 | 100 |  |  |  | 33 | = sub { wantarray ? @result : $result[0] }; | 
|  | 17 |  |  |  |  | 12690 |  | 
| 816 | 11 |  |  |  |  | 17 | $success = eval { $postcondition->( _copy_of(@arguments) ) }; | 
|  | 11 |  |  |  |  | 18 |  | 
| 817 |  |  |  |  |  |  |  | 
| 818 | 11 | 50 |  |  |  | 1453 | if ($@) { | 
|  |  | 100 |  |  |  |  |  | 
| 819 | 0 |  |  |  |  | 0 | croak "postcondition for function died: $@"; | 
| 820 |  |  |  |  |  |  | } | 
| 821 |  |  |  |  |  |  | elsif ( not $success ) { | 
| 822 | 4 |  |  |  |  | 67 | croak | 
| 823 |  |  |  |  |  |  | "postcondition for function failed from $file line $line"; | 
| 824 |  |  |  |  |  |  | } | 
| 825 |  |  |  |  |  |  | else { | 
| 826 | 7 |  |  |  |  | 38 | goto &_real_result; | 
| 827 |  |  |  |  |  |  | } | 
| 828 |  |  |  |  |  |  | } | 
| 829 | 9 |  |  |  |  | 35 | }; | 
| 830 | 9 | 50 |  |  |  | 18 | if ( defined wantarray ) { | 
| 831 | 0 |  |  |  |  | 0 | return $wrapped; | 
| 832 |  |  |  |  |  |  | } | 
| 833 |  |  |  |  |  |  | else { | 
| 834 | 9 |  |  |  |  | 23 | $_[0] = $wrapped; | 
| 835 |  |  |  |  |  |  | } | 
| 836 |  |  |  |  |  |  | } | 
| 837 |  |  |  |  |  |  | else { | 
| 838 | 0 |  |  |  |  | 0 | croak "first argument to precondition() " | 
| 839 |  |  |  |  |  |  | . "was not a method name or code reference"; | 
| 840 |  |  |  |  |  |  | } | 
| 841 |  |  |  |  |  |  | } | 
| 842 |  |  |  |  |  |  |  | 
| 843 |  |  |  |  |  |  | =head2 invariant BLOCK | 
| 844 |  |  |  |  |  |  |  | 
| 845 |  |  |  |  |  |  | BLOCK will be evaluated before and after every public method in the current | 
| 846 |  |  |  |  |  |  | class. A I is described as any subroutine in the package whose | 
| 847 |  |  |  |  |  |  | name begins with a letter and is not composed entirely of uppercase letters. | 
| 848 |  |  |  |  |  |  |  | 
| 849 |  |  |  |  |  |  | Invariants will not be evaluated for class methods. More specifically, | 
| 850 |  |  |  |  |  |  | invariants will only be evaluated when the first argument to a subroutine is | 
| 851 |  |  |  |  |  |  | a blessed reference. This would mean that invariants would not be checked for | 
| 852 |  |  |  |  |  |  | constructors, but C provides another function, | 
| 853 |  |  |  |  |  |  | L<"specify_constructors">, which is used for this purpose. (See the following | 
| 854 |  |  |  |  |  |  | section for details.) | 
| 855 |  |  |  |  |  |  |  | 
| 856 |  |  |  |  |  |  | Invariant BLOCKS are provided with only one argument: the current object. An | 
| 857 |  |  |  |  |  |  | exception is if the method is a constructor, the only argument to the BLOCK is | 
| 858 |  |  |  |  |  |  | the first return value of the method. (If your constructors return an object as | 
| 859 |  |  |  |  |  |  | the first or only return value -- as they normally do -- this means you're | 
| 860 |  |  |  |  |  |  | fine.) | 
| 861 |  |  |  |  |  |  |  | 
| 862 |  |  |  |  |  |  | Invariants are not checked when destructors are invoked. For an explanation as | 
| 863 |  |  |  |  |  |  | to why, see L<"WHITEPAPER">. | 
| 864 |  |  |  |  |  |  |  | 
| 865 |  |  |  |  |  |  | You can use this keyword multiple times to declare multiple invariant contracts | 
| 866 |  |  |  |  |  |  | for the class. | 
| 867 |  |  |  |  |  |  |  | 
| 868 |  |  |  |  |  |  | =head3 Blame | 
| 869 |  |  |  |  |  |  |  | 
| 870 |  |  |  |  |  |  | Blaming violators of invariants is easy. If an invariant contract fails | 
| 871 |  |  |  |  |  |  | following a method invocation, we assume that the check prior to the | 
| 872 |  |  |  |  |  |  | invocation must have succeeded, so the implementation of the method is at | 
| 873 |  |  |  |  |  |  | fault. If an invariant fails before the method runs, invariants must have | 
| 874 |  |  |  |  |  |  | succeeded after the last method was called, so the object must have been | 
| 875 |  |  |  |  |  |  | tampered with by an exogenous source. Eeek! | 
| 876 |  |  |  |  |  |  |  | 
| 877 |  |  |  |  |  |  | =head3 Example | 
| 878 |  |  |  |  |  |  |  | 
| 879 |  |  |  |  |  |  | For example, say that you have a class for Othello boards, which are typically | 
| 880 |  |  |  |  |  |  | 8x8 grids. Othello begins with four pieces already placed on the board and ends | 
| 881 |  |  |  |  |  |  | when the board is full or there are no remaining moves. Thus, the board must | 
| 882 |  |  |  |  |  |  | always have between four and sixty-four pieces, inclusive: | 
| 883 |  |  |  |  |  |  |  | 
| 884 |  |  |  |  |  |  | invariant sub { | 
| 885 |  |  |  |  |  |  | my ( $self ) = @_; | 
| 886 |  |  |  |  |  |  | return ( $self->pieces >= 4 and $self->pieces <= 64 ); | 
| 887 |  |  |  |  |  |  | }; | 
| 888 |  |  |  |  |  |  |  | 
| 889 |  |  |  |  |  |  | If the invariant fails after a method is called, the method's implementation is | 
| 890 |  |  |  |  |  |  | at fault. If the invariant fails before the method is run, an outside source has | 
| 891 |  |  |  |  |  |  | tampered with the object. | 
| 892 |  |  |  |  |  |  |  | 
| 893 |  |  |  |  |  |  | =cut | 
| 894 |  |  |  |  |  |  |  | 
| 895 |  |  |  |  |  |  | sub invariant { | 
| 896 | 11 |  |  | 11 | 1 | 6806 | my ($block) = @_; | 
| 897 | 11 |  |  |  |  | 60 | my ( $package, $file, $line ) = caller(); | 
| 898 | 11 | 50 |  |  |  | 380 | croak "argument to invariant() was not a subroutine reference" | 
| 899 |  |  |  |  |  |  | unless ref $block eq 'CODE'; | 
| 900 |  |  |  |  |  |  |  | 
| 901 | 11 |  |  |  |  | 23 | my %seen; | 
| 902 |  |  |  |  |  |  | my @classes | 
| 903 | 11 | 100 |  |  |  | 18 | = ( $package, @{ Class::Inspector->subclasses($package) || [] } ); | 
|  | 11 |  |  |  |  | 65 |  | 
| 904 | 11 |  |  |  |  | 142119 | foreach my $class (@classes) { | 
| 905 | 91 |  | 100 |  |  | 907 | my @methods = | 
|  |  |  | 50 |  |  |  |  | 
| 906 |  |  |  |  |  |  |  | 
| 907 |  |  |  |  |  |  | # ignore subs imported from Class::Agreement | 
| 908 |  |  |  |  |  |  | grep { | 
| 909 | 105 |  |  |  |  | 190 | 0 + ( __PACKAGE__->can($_) || 0 ) | 
| 910 |  |  |  |  |  |  | != 0 + ( $class->can($_) || 0 ) | 
| 911 |  |  |  |  |  |  | } | 
| 912 |  |  |  |  |  |  |  | 
| 913 |  |  |  |  |  |  | # skip methods we've already added contracts for | 
| 914 | 107 |  |  |  |  | 2397 | grep { not $seen{$_}++ } | 
| 915 |  |  |  |  |  |  |  | 
| 916 |  |  |  |  |  |  | # skip internal methods (DESTROY, etc.) | 
| 917 | 13 | 50 |  |  |  | 69 | grep {/[a-z]/} | 
| 918 |  |  |  |  |  |  |  | 
| 919 |  |  |  |  |  |  | # retrieve all non _* methods from $package | 
| 920 | 13 |  |  |  |  | 33 | @{ Class::Inspector->methods( $class, 'public' ) || [] }; | 
| 921 |  |  |  |  |  |  |  | 
| 922 | 13 |  |  |  |  | 44 | foreach my $method (@methods) { | 
| 923 | 25 |  |  |  |  | 119 | _add_contract_for_hierarchy( $class, $method, | 
| 924 |  |  |  |  |  |  | invar => [ $block, $file, $line ] ); | 
| 925 |  |  |  |  |  |  | } | 
| 926 |  |  |  |  |  |  | } | 
| 927 |  |  |  |  |  |  | } | 
| 928 |  |  |  |  |  |  |  | 
| 929 |  |  |  |  |  |  | =head2 specify_constructors LIST | 
| 930 |  |  |  |  |  |  |  | 
| 931 |  |  |  |  |  |  | As described above, invariants are checked on public methods when the first | 
| 932 |  |  |  |  |  |  | argument is an object. Since constructors are typically class methods (if not | 
| 933 |  |  |  |  |  |  | also object methods), C needs to know which methods are | 
| 934 |  |  |  |  |  |  | constructors so that it can check invariants against the constructors' return | 
| 935 |  |  |  |  |  |  | values instead of simply ignoring them. | 
| 936 |  |  |  |  |  |  |  | 
| 937 |  |  |  |  |  |  | By default, it is assumed that a method named C is the constructor. You | 
| 938 |  |  |  |  |  |  | don't have to bother with this keyword if you don't specify any invariants or if | 
| 939 |  |  |  |  |  |  | your only constructor is C. | 
| 940 |  |  |  |  |  |  |  | 
| 941 |  |  |  |  |  |  | If your class has more constructors, you should specify all of them (including | 
| 942 |  |  |  |  |  |  | C) with C so that invariants can be checked properly: | 
| 943 |  |  |  |  |  |  |  | 
| 944 |  |  |  |  |  |  | package Othello::Board; | 
| 945 |  |  |  |  |  |  | use Class::Agreement; | 
| 946 |  |  |  |  |  |  |  | 
| 947 |  |  |  |  |  |  | specify_constructors qw( new new_random ); | 
| 948 |  |  |  |  |  |  |  | 
| 949 |  |  |  |  |  |  | invariant sub { | 
| 950 |  |  |  |  |  |  | my ( $self ) = @_; | 
| 951 |  |  |  |  |  |  | return ( $self->pieces >= 4 and $self->pieces <= 64 ); | 
| 952 |  |  |  |  |  |  | }; | 
| 953 |  |  |  |  |  |  |  | 
| 954 |  |  |  |  |  |  | sub new { | 
| 955 |  |  |  |  |  |  | ... | 
| 956 |  |  |  |  |  |  | return bless [], shift; | 
| 957 |  |  |  |  |  |  | } | 
| 958 |  |  |  |  |  |  |  | 
| 959 |  |  |  |  |  |  | sub new_random { | 
| 960 |  |  |  |  |  |  | ... | 
| 961 |  |  |  |  |  |  | return bless [], shift; | 
| 962 |  |  |  |  |  |  | } | 
| 963 |  |  |  |  |  |  |  | 
| 964 |  |  |  |  |  |  | Any subclasses of C would also have the invariants of the | 
| 965 |  |  |  |  |  |  | methods C and C checked as constructors. You can override | 
| 966 |  |  |  |  |  |  | the specified constructors of any class -- all subclasses will use the settings | 
| 967 |  |  |  |  |  |  | specified by their parents. | 
| 968 |  |  |  |  |  |  |  | 
| 969 |  |  |  |  |  |  | If, for some reason, your class has no constructors, you can pass | 
| 970 |  |  |  |  |  |  | C an empty list: | 
| 971 |  |  |  |  |  |  |  | 
| 972 |  |  |  |  |  |  | specify_constructors (); | 
| 973 |  |  |  |  |  |  |  | 
| 974 |  |  |  |  |  |  | =cut | 
| 975 |  |  |  |  |  |  |  | 
| 976 |  |  |  |  |  |  | sub specify_constructors { | 
| 977 | 3 |  |  | 3 | 1 | 16 | my (@constructors) = @_; | 
| 978 | 3 |  |  |  |  | 15 | my ( $package, $file, $line ) = caller(); | 
| 979 | 3 |  |  |  |  | 98 | _set_constructors( $package, @constructors ); | 
| 980 |  |  |  |  |  |  | } | 
| 981 |  |  |  |  |  |  |  | 
| 982 |  |  |  |  |  |  | =head1 REAL-LIFE EXAMPLES | 
| 983 |  |  |  |  |  |  |  | 
| 984 |  |  |  |  |  |  | =head2 Checking a method's input | 
| 985 |  |  |  |  |  |  |  | 
| 986 |  |  |  |  |  |  | Say that you have a board game that uses a graph of tiles. Every turn, players | 
| 987 |  |  |  |  |  |  | draw a tile and, if it's placable, plop it into the graph. The method | 
| 988 |  |  |  |  |  |  | C of the C class should take a placable tile as an | 
| 989 |  |  |  |  |  |  | argument, which we can express as a contract: | 
| 990 |  |  |  |  |  |  |  | 
| 991 |  |  |  |  |  |  | precondition insert_tile => sub { | 
| 992 |  |  |  |  |  |  | my ( $self, $tile ) = @_; | 
| 993 |  |  |  |  |  |  | return $self->verify_tile_fits( $tile ); | 
| 994 |  |  |  |  |  |  | }; | 
| 995 |  |  |  |  |  |  |  | 
| 996 |  |  |  |  |  |  | sub insert_tile { | 
| 997 |  |  |  |  |  |  | my ( $self, $tile ) = @_; | 
| 998 |  |  |  |  |  |  | ... | 
| 999 |  |  |  |  |  |  | } | 
| 1000 |  |  |  |  |  |  |  | 
| 1001 |  |  |  |  |  |  | Before the implementation of C is executed, the precondition | 
| 1002 |  |  |  |  |  |  | checks to ensure that C<$tile> is placable in the graph as determined by | 
| 1003 |  |  |  |  |  |  | C. | 
| 1004 |  |  |  |  |  |  |  | 
| 1005 |  |  |  |  |  |  | =head2 Checking a method's output | 
| 1006 |  |  |  |  |  |  |  | 
| 1007 |  |  |  |  |  |  | Using the C class from the previous example, say we have a method | 
| 1008 |  |  |  |  |  |  | C which, given an C and C, will return all tiles | 
| 1009 |  |  |  |  |  |  | surrounding the tile at that position. If the tiles are square, any given tile | 
| 1010 |  |  |  |  |  |  | shouldn't have more than eight neighbors: | 
| 1011 |  |  |  |  |  |  |  | 
| 1012 |  |  |  |  |  |  | sub get_neighbors { | 
| 1013 |  |  |  |  |  |  | my ( $self, $x, $y ) = @_; | 
| 1014 |  |  |  |  |  |  | ... | 
| 1015 |  |  |  |  |  |  | } | 
| 1016 |  |  |  |  |  |  |  | 
| 1017 |  |  |  |  |  |  | postcondition get_neighbors => sub { | 
| 1018 |  |  |  |  |  |  | return ( (result) <= 8 ); | 
| 1019 |  |  |  |  |  |  | }; | 
| 1020 |  |  |  |  |  |  |  | 
| 1021 |  |  |  |  |  |  | The postcondition ensures that C returns no more than eight | 
| 1022 |  |  |  |  |  |  | items. | 
| 1023 |  |  |  |  |  |  |  | 
| 1024 |  |  |  |  |  |  | =head2 Testing old values | 
| 1025 |  |  |  |  |  |  |  | 
| 1026 |  |  |  |  |  |  | Dependent contracts occur when the postcondition I on the input given | 
| 1027 |  |  |  |  |  |  | to the method. You can use dependent contracts to save old copies of values | 
| 1028 |  |  |  |  |  |  | through the use of closure. | 
| 1029 |  |  |  |  |  |  |  | 
| 1030 |  |  |  |  |  |  | Given the C class from previous examples, say that the tiles in the | 
| 1031 |  |  |  |  |  |  | graph are stored in a list. If insert tile has successfully added the tile to | 
| 1032 |  |  |  |  |  |  | the graph, the number of tiles in the graph should have increased by one. Using | 
| 1033 |  |  |  |  |  |  | the C function, we return a closure that will check exactly this: | 
| 1034 |  |  |  |  |  |  |  | 
| 1035 |  |  |  |  |  |  | dependent insert_tile => sub { | 
| 1036 |  |  |  |  |  |  | my ( $self, $tile ) = @_; | 
| 1037 |  |  |  |  |  |  | my $old_count = $self->num_tiles; | 
| 1038 |  |  |  |  |  |  | return sub { | 
| 1039 |  |  |  |  |  |  | my ( $self, $tile ) = @_; | 
| 1040 |  |  |  |  |  |  | return ( $self->num_tiles > $old_count ); | 
| 1041 |  |  |  |  |  |  | }; | 
| 1042 |  |  |  |  |  |  | }; | 
| 1043 |  |  |  |  |  |  |  | 
| 1044 |  |  |  |  |  |  | sub insert_tile { | 
| 1045 |  |  |  |  |  |  | my ( $self, $tile ) = @_; | 
| 1046 |  |  |  |  |  |  | ... | 
| 1047 |  |  |  |  |  |  | } | 
| 1048 |  |  |  |  |  |  |  | 
| 1049 |  |  |  |  |  |  | Before the implementation of C is run, the block given to | 
| 1050 |  |  |  |  |  |  | C is run, which returns a closure. This closure is then run after | 
| 1051 |  |  |  |  |  |  | C as if it were a precondition. (Thus, the closure returned by | 
| 1052 |  |  |  |  |  |  | the block may make use the C function as well as C<@_>.) | 
| 1053 |  |  |  |  |  |  |  | 
| 1054 |  |  |  |  |  |  | =head2 Contracts on coderefs | 
| 1055 |  |  |  |  |  |  |  | 
| 1056 |  |  |  |  |  |  | This is where contracts get interesting. Say that you have a function C | 
| 1057 |  |  |  |  |  |  | that takes a function C as an argument and returns a number greater than | 
| 1058 |  |  |  |  |  |  | zero. However, C has a contract, too: it must take a natural number as the | 
| 1059 |  |  |  |  |  |  | first argument and must return a single letter of the alphabet. This can be | 
| 1060 |  |  |  |  |  |  | represented as follows: | 
| 1061 |  |  |  |  |  |  |  | 
| 1062 |  |  |  |  |  |  | precondition g => sub { | 
| 1063 |  |  |  |  |  |  | # first argument of @_ is f() | 
| 1064 |  |  |  |  |  |  | precondition $_[0] => sub { | 
| 1065 |  |  |  |  |  |  | my ( $val ) = @_; | 
| 1066 |  |  |  |  |  |  | return ( $val =~ /^\d+$/ ); | 
| 1067 |  |  |  |  |  |  | }; | 
| 1068 |  |  |  |  |  |  | postcondition $_[0] => sub { | 
| 1069 |  |  |  |  |  |  | return ( result =~ /^[A-Z]$/i ); | 
| 1070 |  |  |  |  |  |  | }; | 
| 1071 |  |  |  |  |  |  | }; | 
| 1072 |  |  |  |  |  |  |  | 
| 1073 |  |  |  |  |  |  | sub g { | 
| 1074 |  |  |  |  |  |  | my ($f) = @_; | 
| 1075 |  |  |  |  |  |  | ... # call $f somehow | 
| 1076 |  |  |  |  |  |  | } | 
| 1077 |  |  |  |  |  |  |  | 
| 1078 |  |  |  |  |  |  | postcondition g => sub { | 
| 1079 |  |  |  |  |  |  | return ( result > 0 ); | 
| 1080 |  |  |  |  |  |  | }; | 
| 1081 |  |  |  |  |  |  |  | 
| 1082 |  |  |  |  |  |  | Thus, when the function C is used within C, the contracts set up for | 
| 1083 |  |  |  |  |  |  | C in the precondition apply to it. | 
| 1084 |  |  |  |  |  |  |  | 
| 1085 |  |  |  |  |  |  | =head1 FAQ | 
| 1086 |  |  |  |  |  |  |  | 
| 1087 |  |  |  |  |  |  | =head2 Aren't contracts just assertions I could write with something like C ? | 
| 1088 |  |  |  |  |  |  |  | 
| 1089 |  |  |  |  |  |  | The answer to this has been nicely worded by Jim Weirich in "Design by Contract | 
| 1090 |  |  |  |  |  |  | and Unit Testing" located at | 
| 1091 |  |  |  |  |  |  | L: | 
| 1092 |  |  |  |  |  |  |  | 
| 1093 |  |  |  |  |  |  | "Although Design by Contract and assertions are very closely related, DbC is | 
| 1094 |  |  |  |  |  |  | more than just slapping a few assertions into your code at strategic locations. | 
| 1095 |  |  |  |  |  |  | It is about identifying the contract under which your code will execute and you | 
| 1096 |  |  |  |  |  |  | expect all clients to adhere to. It is about clearly defining responsibilities | 
| 1097 |  |  |  |  |  |  | between client software and supplier software. | 
| 1098 |  |  |  |  |  |  |  | 
| 1099 |  |  |  |  |  |  | "In short, Design by Contract starts by specifying the conditions under which | 
| 1100 |  |  |  |  |  |  | it is legal to call a method. It is the responsibility of the client software | 
| 1101 |  |  |  |  |  |  | to ensure these conditions (called preconditions) are met. | 
| 1102 |  |  |  |  |  |  |  | 
| 1103 |  |  |  |  |  |  | "Given that the preconditions are met, the method in the supplier software | 
| 1104 |  |  |  |  |  |  | guarantees that certion other conditions will be true when the method returns. | 
| 1105 |  |  |  |  |  |  | These are called postcondition, and are the responsibility of the supplier code | 
| 1106 |  |  |  |  |  |  | in ensure." | 
| 1107 |  |  |  |  |  |  |  | 
| 1108 |  |  |  |  |  |  | =head2 Why not just use Carp::Assert? | 
| 1109 |  |  |  |  |  |  |  | 
| 1110 |  |  |  |  |  |  | Use L and L if you need to check I. If you | 
| 1111 |  |  |  |  |  |  | want to assert I, L does everything that | 
| 1112 |  |  |  |  |  |  | L can do for you B it determines which components are faulty | 
| 1113 |  |  |  |  |  |  | when something fails. | 
| 1114 |  |  |  |  |  |  |  | 
| 1115 |  |  |  |  |  |  | If you're looking for the sexiness of L, try using | 
| 1116 |  |  |  |  |  |  | L with something like L: | 
| 1117 |  |  |  |  |  |  |  | 
| 1118 |  |  |  |  |  |  | use Class::Agreement; | 
| 1119 |  |  |  |  |  |  | use Data::Validate qw(:math :string); | 
| 1120 |  |  |  |  |  |  |  | 
| 1121 |  |  |  |  |  |  | precondition foo => sub { is_integer( $_[1] ) }; | 
| 1122 |  |  |  |  |  |  | precondition bar => sub { is_greater_than( $_[1], 0 ) }; | 
| 1123 |  |  |  |  |  |  | precondition baz => sub { is_alphanumeric( $_[1] ) }; | 
| 1124 |  |  |  |  |  |  |  | 
| 1125 |  |  |  |  |  |  | =head2 How do I save an old copy of the object? | 
| 1126 |  |  |  |  |  |  |  | 
| 1127 |  |  |  |  |  |  | Hopefully you don't need to. Just save the variable (or variables) you need to | 
| 1128 |  |  |  |  |  |  | check in the postcondition by creating closures. See L"Testing old values"> | 
| 1129 |  |  |  |  |  |  | for an example of how to do this. | 
| 1130 |  |  |  |  |  |  |  | 
| 1131 |  |  |  |  |  |  | =head2 How do I disable contracts? | 
| 1132 |  |  |  |  |  |  |  | 
| 1133 |  |  |  |  |  |  | Before you ask this, B. If your contracts | 
| 1134 |  |  |  |  |  |  | are slowing down your program, first try following these guidelines: | 
| 1135 |  |  |  |  |  |  |  | 
| 1136 |  |  |  |  |  |  | =over 4 | 
| 1137 |  |  |  |  |  |  |  | 
| 1138 |  |  |  |  |  |  | =item * B | 
| 1139 |  |  |  |  |  |  |  | 
| 1140 |  |  |  |  |  |  | Cloning in Perl is expensive. Hopefully you've read the above examples on | 
| 1141 |  |  |  |  |  |  | L"Testing old values"> and have realized that cloning an object isn't | 
| 1142 |  |  |  |  |  |  | necessary. | 
| 1143 |  |  |  |  |  |  |  | 
| 1144 |  |  |  |  |  |  | =item * B | 
| 1145 |  |  |  |  |  |  |  | 
| 1146 |  |  |  |  |  |  | If your contract is performing the exact same tasks or calculations that are in | 
| 1147 |  |  |  |  |  |  | the function itself, toss it. Only code the essentials into the contracts, such | 
| 1148 |  |  |  |  |  |  | as "this function returns a number greater than twelve" or "the object was | 
| 1149 |  |  |  |  |  |  | modified in this mannar." | 
| 1150 |  |  |  |  |  |  |  | 
| 1151 |  |  |  |  |  |  | =item * B | 
| 1152 |  |  |  |  |  |  |  | 
| 1153 |  |  |  |  |  |  | You can if you want, but contracts are designed to be I | 
| 1154 |  |  |  |  |  |  | behavior>, not to enforce the types of data structures you're passing around. | 
| 1155 |  |  |  |  |  |  |  | 
| 1156 |  |  |  |  |  |  | =back | 
| 1157 |  |  |  |  |  |  |  | 
| 1158 |  |  |  |  |  |  | If you really want to disable this module, replace C | 
| 1159 |  |  |  |  |  |  | C | 
| 1160 |  |  |  |  |  |  | do nothing. | 
| 1161 |  |  |  |  |  |  |  | 
| 1162 |  |  |  |  |  |  | =head2 What do you mean, "There's a problem with the hierarchy?" | 
| 1163 |  |  |  |  |  |  |  | 
| 1164 |  |  |  |  |  |  | The Liskov-Wing principle states, "The objects of subtype ought to behave the | 
| 1165 |  |  |  |  |  |  | same as those of the supertype as far as anyone or any program using the | 
| 1166 |  |  |  |  |  |  | supertype objects can tell." (See: "Liskov Wing Subtyping" at | 
| 1167 |  |  |  |  |  |  | L.) Say that C is a parent | 
| 1168 |  |  |  |  |  |  | class of C, and both classes implement a method C, and both | 
| 1169 |  |  |  |  |  |  | implementations have pre- and postconditions. According to Liskov-Wing, the | 
| 1170 |  |  |  |  |  |  | valid input of C should be a I of the valid input of | 
| 1171 |  |  |  |  |  |  | C. Thus, if the precondition for C fails but the | 
| 1172 |  |  |  |  |  |  | precondition for C passes, the class heiarchy fails the principle. | 
| 1173 |  |  |  |  |  |  | Postconditions are the opposite: the output of C should be | 
| 1174 |  |  |  |  |  |  | a I of the output of C. If the postcondition for | 
| 1175 |  |  |  |  |  |  | C passes but the postcondition for C fails, this | 
| 1176 |  |  |  |  |  |  | violates the principle. | 
| 1177 |  |  |  |  |  |  |  | 
| 1178 |  |  |  |  |  |  | =head2 Can I modify the argument list? | 
| 1179 |  |  |  |  |  |  |  | 
| 1180 |  |  |  |  |  |  | If the argument list C<@_> is made up of simple scalars, no. However, if the | 
| 1181 |  |  |  |  |  |  | method or function is passed a reference of some sort. This is a Bad Thing | 
| 1182 |  |  |  |  |  |  | because your code should | 
| 1183 |  |  |  |  |  |  |  | 
| 1184 |  |  |  |  |  |  | =head2 How can I type less? | 
| 1185 |  |  |  |  |  |  |  | 
| 1186 |  |  |  |  |  |  | ...or more ugly? Use implicit returns and don't name your variables. For | 
| 1187 |  |  |  |  |  |  | example, the dependent contract in L"Dependent Contracts"> could be written as | 
| 1188 |  |  |  |  |  |  | follows: | 
| 1189 |  |  |  |  |  |  |  | 
| 1190 |  |  |  |  |  |  | dependent insert_tile => sub { | 
| 1191 |  |  |  |  |  |  | my $o = shift()->num_tiles; | 
| 1192 |  |  |  |  |  |  | sub { shift()->num_tiles > $o }; | 
| 1193 |  |  |  |  |  |  | }; | 
| 1194 |  |  |  |  |  |  |  | 
| 1195 |  |  |  |  |  |  | Other examples: | 
| 1196 |  |  |  |  |  |  |  | 
| 1197 |  |  |  |  |  |  | precondition sqrt => sub { shift() > 0 }; | 
| 1198 |  |  |  |  |  |  |  | 
| 1199 |  |  |  |  |  |  | postcondition digits => sub { result =~ /^\d+$/ }; | 
| 1200 |  |  |  |  |  |  |  | 
| 1201 |  |  |  |  |  |  | invariant sub { shift()->size > 4 }; | 
| 1202 |  |  |  |  |  |  |  | 
| 1203 |  |  |  |  |  |  | Or, write your own generator to make things clean: | 
| 1204 |  |  |  |  |  |  |  | 
| 1205 |  |  |  |  |  |  | sub argument_is_divisible_by { | 
| 1206 |  |  |  |  |  |  | my $num = shift; | 
| 1207 |  |  |  |  |  |  | return sub { not $_[1] % $num }; | 
| 1208 |  |  |  |  |  |  | } | 
| 1209 |  |  |  |  |  |  |  | 
| 1210 |  |  |  |  |  |  | precondition foo => argument_is_divisible_by(2); | 
| 1211 |  |  |  |  |  |  | precondition bar => argument_is_divisible_by(3); | 
| 1212 |  |  |  |  |  |  |  | 
| 1213 |  |  |  |  |  |  | =head2 What if I generate methods? | 
| 1214 |  |  |  |  |  |  |  | 
| 1215 |  |  |  |  |  |  | There's no problem as long as you build your subroutines before runtime, | 
| 1216 |  |  |  |  |  |  | probably by sticking the generation in a C block. | 
| 1217 |  |  |  |  |  |  |  | 
| 1218 |  |  |  |  |  |  | Here's a snippet from one of the included tests, F. Three | 
| 1219 |  |  |  |  |  |  | methods, C, C and C, are created and given an assertion that the | 
| 1220 |  |  |  |  |  |  | argument passed to them must be greater than zero: | 
| 1221 |  |  |  |  |  |  |  | 
| 1222 |  |  |  |  |  |  | my $assertion = sub { $_[1] > 0 }; | 
| 1223 |  |  |  |  |  |  | precondition foo => $assertion; | 
| 1224 |  |  |  |  |  |  | precondition bar => $assertion; | 
| 1225 |  |  |  |  |  |  | precondition baz => $assertion; | 
| 1226 |  |  |  |  |  |  |  | 
| 1227 |  |  |  |  |  |  | BEGIN { | 
| 1228 |  |  |  |  |  |  | no strict 'refs'; | 
| 1229 |  |  |  |  |  |  | *{$_} = sub { } | 
| 1230 |  |  |  |  |  |  | for qw( foo bar baz ); | 
| 1231 |  |  |  |  |  |  | } | 
| 1232 |  |  |  |  |  |  |  | 
| 1233 |  |  |  |  |  |  | =head1 CAVEATS | 
| 1234 |  |  |  |  |  |  |  | 
| 1235 |  |  |  |  |  |  | =over 4 | 
| 1236 |  |  |  |  |  |  |  | 
| 1237 |  |  |  |  |  |  | =item * You can't add contracts for abstract methods. If you try to add a contract to a method that isn't implemented in the given class or any of its parents, L will croak. One must declare an empty subroutine to get around this. | 
| 1238 |  |  |  |  |  |  |  | 
| 1239 |  |  |  |  |  |  | =item * The C keyword will not properly report void context to any methods with contracts. | 
| 1240 |  |  |  |  |  |  |  | 
| 1241 |  |  |  |  |  |  | =item * The C keyword will return an extra stack frame. | 
| 1242 |  |  |  |  |  |  |  | 
| 1243 |  |  |  |  |  |  | =back | 
| 1244 |  |  |  |  |  |  |  | 
| 1245 |  |  |  |  |  |  | =head1 AUTHOR | 
| 1246 |  |  |  |  |  |  |  | 
| 1247 |  |  |  |  |  |  | Ian Langworth, C<<  >> | 
| 1248 |  |  |  |  |  |  |  | 
| 1249 |  |  |  |  |  |  | =head1 BUGS | 
| 1250 |  |  |  |  |  |  |  | 
| 1251 |  |  |  |  |  |  | Please report any bugs or feature requests to | 
| 1252 |  |  |  |  |  |  | C, or through the web interface at | 
| 1253 |  |  |  |  |  |  | L. | 
| 1254 |  |  |  |  |  |  | I will be notified, and then you'll automatically be notified of progress on | 
| 1255 |  |  |  |  |  |  | your bug as I make changes. | 
| 1256 |  |  |  |  |  |  |  | 
| 1257 |  |  |  |  |  |  | =head1 ACKNOWLEDGEMENTS | 
| 1258 |  |  |  |  |  |  |  | 
| 1259 |  |  |  |  |  |  | Thanks to Prof. Matthias Felleisen who granted me a directed study to pursue | 
| 1260 |  |  |  |  |  |  | this project and guided me during its development. | 
| 1261 |  |  |  |  |  |  |  | 
| 1262 |  |  |  |  |  |  | Thanks to a number of other people who contributed to this module in some way, | 
| 1263 |  |  |  |  |  |  | including: Damian Conway, Simon Cozens, Dan "Lamech" Friedman, Uri Guttman, | 
| 1264 |  |  |  |  |  |  | Christian Hansen, Adrian Howard, David Landgren, Curtis "Ovid" Poe, Ricardo | 
| 1265 |  |  |  |  |  |  | SIGNES, Richard Soderburg, Jesse Vincent. | 
| 1266 |  |  |  |  |  |  |  | 
| 1267 |  |  |  |  |  |  | =head1 SEE ALSO | 
| 1268 |  |  |  |  |  |  |  | 
| 1269 |  |  |  |  |  |  | L, L, L, L, | 
| 1270 |  |  |  |  |  |  | L | 
| 1271 |  |  |  |  |  |  |  | 
| 1272 |  |  |  |  |  |  | L, | 
| 1273 |  |  |  |  |  |  | L | 
| 1274 |  |  |  |  |  |  |  | 
| 1275 |  |  |  |  |  |  | =head1 COPYRIGHT & LICENSE | 
| 1276 |  |  |  |  |  |  |  | 
| 1277 |  |  |  |  |  |  | Copyright 2005 Ian Langworth, All Rights Reserved. | 
| 1278 |  |  |  |  |  |  |  | 
| 1279 |  |  |  |  |  |  | This program is free software; you can redistribute it and/or modify it | 
| 1280 |  |  |  |  |  |  | under the same terms as Perl itself. | 
| 1281 |  |  |  |  |  |  |  | 
| 1282 |  |  |  |  |  |  | =cut | 
| 1283 |  |  |  |  |  |  |  | 
| 1284 |  |  |  |  |  |  | 1;    # End of Class::Agreement | 
| 1285 |  |  |  |  |  |  |  |