File Coverage

blib/lib/Sub/SymMethod.pm
Criterion Covered Total %
statement 163 188 86.7
branch 53 76 69.7
condition 26 51 50.9
subroutine 32 32 100.0
pod 12 12 100.0
total 286 359 79.6


line stmt bran cond sub pod time code
1 2     2   113102 use 5.008008;
  2         14  
2 2     2   12 use strict;
  2         4  
  2         37  
3 2     2   8 use warnings;
  2         3  
  2         153  
4              
5              
6             our $AUTHORITY = 'cpan:TOBYINK';
7             our $VERSION = '1.000';
8              
9             use Exporter::Shiny our @EXPORT = qw( symmethod );
10 2     2   731 use Scalar::Util qw( blessed );
  2         7979  
  2         14  
11 2     2   103 use Role::Hooks;
  2         3  
  2         70  
12 2     2   784  
  2         9350  
  2         188  
13             # Options other than these will be passed through to
14             # Type::Params.
15             #
16             my %KNOWN_OPTIONS = (
17             code => 1,
18             name => 1,
19             named => 'legacy',
20             no_dispatcher => 1,
21             no_hook => 1,
22             order => 1,
23             origin => 1,
24             signature => 'legacy',
25             signature_spec => 1,
26             );
27              
28             # But not these!
29             #
30             my %BAD_OPTIONS = (
31             want_details => 1,
32             want_object => 1,
33             want_source => 1,
34             goto_next => 1,
35             on_die => 1,
36             message => 1,
37             );
38              
39             BEGIN {
40             eval { require mro }
41 2         14 or do { require MRO::Compat };
42 2 50   2   6
  0         0  
43             eval {
44             require Types::Standard;
45 2         1033 'Types::Standard'->import(qw/ is_CodeRef is_HashRef is_ArrayRef is_Int /);
46 2         176099 1;
47 2         4502 }
48             or do {
49 2 50       3 *is_CodeRef = sub { no warnings; ref($_[0]) eq 'CODE' };
50 2     2   12 *is_HashRef = sub { no warnings; ref($_[0]) eq 'HASH' };
  2         4  
  2         96  
  0         0  
  0         0  
51 2     2   10 *is_ArrayRef = sub { no warnings; ref($_[0]) eq 'ARRAY' };
  2         2  
  2         115  
  0         0  
  0         0  
52 2     2   12 *is_Int = sub { defined($_[0]) and !ref($_[0]) and $_[0] =~ /\A-[0-9]+\z/ };
  2         3  
  2         213  
  0         0  
  0         0  
53 0 0 0     0 };
  0         0  
54            
55             no strict 'refs';
56 2     2   30 eval { require Sub::Util; 'Sub::Util'->import('set_subname'); 1 }
  2         4  
  2         155  
57 2         12 or do { require Sub::Name; *set_subname = \&Sub::Name::subname; }
  2         59  
  2         1381  
58 2 50       5 };
  0         0  
  0         0  
59              
60             {
61             # %SPECS is a hash of hashrefs keyed on {package}->{subname}.
62             # The values are specs (themselves hashrefs!)
63             my %SPECS;
64            
65             my ( $class, $target, $name ) = ( shift, @_ );
66             $SPECS{$target}{$name} ||= [];
67 24     24 1 38 }
68 24   100     78
69             my ( $class, $target ) = ( shift, @_ );
70             keys %{ $SPECS{$target} ||= {} };
71             }
72 12     12 1 21 }
73 12   50     14  
  12         37  
74             my ( $me, $target, $sub_name, $spec ) = ( shift, @_ );
75            
76             my %tp = ( method => 1 );
77             $tp{method} = $spec->{method} if defined $spec->{method};
78 14     14   26
79             if ( is_ArrayRef $spec->{signature} ) {
80 14         24 my $key = $spec->{named} ? 'named' : 'positional';
81 14 50       35 $tp{$key} = delete $spec->{signature};
82             }
83 14 100       56 else {
84 1 50       3 $tp{named} = $spec->{named} if ref $spec->{named};
85 1         3 }
86            
87             # Options which are not known by this module must be intended for
88 13 100       32 # Type::Params instead.
89             for my $key ( keys %$spec ) {
90            
91             next if ( $KNOWN_OPTIONS{$key} or $key =~ /^_/ );
92            
93 14         38 if ( $BAD_OPTIONS{$key} ) {
94             require Carp;
95 72 100 66     145 Carp::carp( "Unsupported option: $key" );
96             next;
97 14 50       29 }
98 0         0
99 0         0 $tp{$key} = delete $spec->{$key};
100 0         0 }
101            
102             $tp{package} ||= $target;
103 14         26 $tp{subname} ||= ref( $sub_name ) ? '__ANON__' : $sub_name;
104            
105             # Historically we allowed method=2, etc
106 14   33     55 if ( is_Int $tp{method} ) {
107 14 50 33     47 if ( $tp{method} > 1 ) {
108             require Types::Standard;
109             my $excess = $tp{method} - 1;
110 14 50       32 $tp{method} = 1;
111 14 50       26 ref( $tp{head} ) ? push( @{ $tp{head} }, ( Types::Standard::Any() ) x $excess ) : ( $tp{head} += $excess );
112 0         0 }
113 0         0 }
114 0         0
115 0 0       0 $spec->{signature_spec} = \%tp
  0         0  
116             if $tp{positional} || $tp{pos} || $tp{named} || $tp{multiple} || $tp{multi};
117             }
118              
119             my ( $class, $target, $name, %args ) = ( shift, @_ );
120 14 100 33     86 $args{origin} = $target unless exists $args{origin};
      66        
      66        
      33        
121             $args{method} = 1 unless exists $args{method};
122             $args{name} = $name;
123             $args{order} = 0 unless exists $args{order};
124 14     14 1 39
125 14 50       31 $class->_extract_type_params_spec( $target, $name, \%args );
126 14 50       33
127 14         16 if ( not is_CodeRef $args{code} ) {
128 14 100       27 require Carp;
129             Carp::croak('Cannot install symmethod with no valid code; stopped');
130 14         33 }
131            
132 14 50       33 my $symmethods = $class->get_symmethods( $target, $name );
133 0         0 push @$symmethods, \%args;
134 0         0 $class->clear_cache($name);
135            
136             my $kind = 'Role::Hooks'->is_role($target) ? 'role' : 'class';
137 14         27
138 14         21 if ( $kind eq 'class' and not $args{no_dispatcher} ) {
139 14         31 $class->install_dispatcher( $target, $name );
140             }
141 14 100       33
142             if ( $kind eq 'role' and not $args{no_hook} ) {
143 14 100 66     299 $class->install_hooks( $target );
144 8         17 }
145            
146             return $class;
147 14 100 66     43 }
148 6         12  
149              
150             {
151 14         22 my %KNOWN;
152             my ( $class, $coderef, $set ) = ( shift, @_ );
153             if ( @_ == 2 ) {
154             $KNOWN{"$coderef"} = $set;
155             }
156             $KNOWN{"$coderef"};
157             }
158 12     12 1 25 }
159 12 100       32  
160 2         8 my ( $class, $target, $name ) = ( shift, @_ );
161            
162 12         43 if ( my $existing = $target->can($name) ) {
163             return if $class->is_dispatcher( $existing );
164             require Carp;
165             Carp::carp("Symmethod $name overriding existing method for class $target");
166             }
167 12     12 1 23
168             if ( $name eq 'BUILD' or $name eq 'DEMOLISH' or $name eq 'new' ) {
169 12 100       90 require Carp;
170 10 50       21 Carp::carp("Symmethod $name should probably be a plain method");
171 0         0 }
172 0         0
173             my $coderef = $class->build_dispatcher( $target, $name );
174             my $qname = "$target\::$name";
175 2 50 33     14
      33        
176 0         0 do {
177 0         0 no strict 'refs';
178             no warnings 'redefine';
179             *$qname = set_subname( $qname, $coderef );
180 2         5 };
181 2         5
182             $class->is_dispatcher( $coderef, $qname );
183 2         3
184 2     2   14 return $class;
  2         2  
  2         75  
185 2     2   17 }
  2         3  
  2         1108  
186 2         34  
187             my ( $class, $target, $name ) = ( shift, @_ );
188            
189 2         9 return sub {
190             my $specs = $class->get_all_symmethods( $_[0], $name );
191 2         4 my @results;
192             SPEC: for my $spec ( @$specs ) {
193             if ( $spec->{signature} or $spec->{signature_spec} ) {
194             $class->compile_signature($spec) unless is_CodeRef $spec->{signature};
195 4     4 1 11 my @orig = @_;
196             my @new;
197             {
198 6     6   35 local $@;
        6      
199 6         9 eval{ @new = $spec->{signature}(@orig); 1 }
200 6         9 or next SPEC;
201 42 100 100     12998 }
202 6 100       34 push @results, scalar $spec->{code}( @new );
203 6         17 next SPEC;
204 6         64 }
205            
206 6         9 push @results, scalar $spec->{code}( @_ );
  6         9  
207 6 100       8 }
  6         20  
  4         131  
208             return @results;
209             };
210 4         13 }
211 4         46  
212             my ( $class, $invocant, $name ) = ( shift, shift, shift, @_ );
213             my $invocant_class = blessed($invocant) || $invocant;
214 36         93
215             my $dispatcher = $class->build_dispatcher( $invocant_class, $name );
216 6         52 unshift @_, $invocant;
217 4         20 goto $dispatcher;
218             }
219              
220             {
221 2     2 1 7 my %HOOKED;
222 2   33     13
223             my ( $class, $target ) = ( shift, @_ );
224 2         9
225 2         5 return if $HOOKED{$target}++;
226 2         6
227             'Role::Hooks'->before_apply( $target, sub {
228             my ( $role, $consumer ) = @_;
229            
230             if ( not 'Role::Hooks'->is_role($consumer) ) {
231             push @{ $class->get_roles_for_class($consumer) }, $target;
232            
233 6     6 1 14 for my $name ( $class->get_symmethod_names($target) ) {
234             $class->install_dispatcher( $consumer, $name );
235 6 100       14 }
236             }
237            
238 8     8   585 $class->clear_cache( $class->get_symmethod_names($target) );
239             } );
240 8 100       18
241 4         77 return $class;
  4         8  
242             }
243 4         8 }
244 4         9  
245             {
246             # %ROLES is a hash keyed on {classname} where the values
247             # are an arrayref of rolenames of roles the class is known to consume.
248 8         57 # We only care about roles which define symmethods.
249 4         20 my %ROLES;
250            
251 4         890 my ( $class, $target ) = ( shift, @_ );
252             $ROLES{$target} ||= [];
253             }
254             }
255              
256             {
257             # %CACHE is a hash of hashrefs keyed on {subname}->{invocantclass}
258             # to avoid needing to crawl MRO for each method call.
259             # The values are arrayrefs of specs
260             my %CACHE;
261            
262 10     10 1 18 my ( $class ) = ( shift );
263 10   100     36 delete $CACHE{$_} for @_;
264             return $class;
265             }
266            
267             my ( $class, $invocant, $name ) = ( shift, @_ );
268             my $invocant_class = blessed($invocant) || $invocant;
269            
270             if ( not $CACHE{$name}{$invocant_class} ) {
271             use sort 'stable';
272             $CACHE{$name}{$invocant_class} = [
273             sort { $a->{order} <=> $b->{order} }
274 22     22 1 29 map @{ $class->get_symmethods( $_, $name ) },
275 22         66 map +( @{ $class->get_roles_for_class($_) }, $_ ),
276 22         34 reverse @{ mro::get_linear_isa( $invocant_class ) || [] }
277             ];
278             Internals::SvREADONLY($CACHE{$name}{$invocant_class}, 1);
279             }
280 6     6 1 13
281 6   33     27 $CACHE{$name}{$invocant_class};
282             }
283 6 100       16 }
284 2     2   1784  
  2         942  
  2         10  
285             my ( $class, $spec ) = ( shift, @_ );
286 24         33 require Type::Params;
287 10         17 $class->_extract_type_params_spec( $spec->{origin}, $spec->{name}, $spec )
288 6         13 unless $spec->{signature_spec};
289 2 50       4 $spec->{signature} = Type::Params::signature( %{ $spec->{signature_spec} } )
  2         11  
290             if keys %{ $spec->{signature_spec} || {} };
291 2         10 return $class;
292             }
293              
294 6         13 my ( $class, undef, undef, $globals ) = ( shift, @_ );
295            
296             my $target = $globals->{into};
297             ref($target) and die 'Cannot export to non-package';
298            
299 2     2 1 5 return sub {
300 2         1005 splice(@_, -1, 0, 'code') unless @_ % 2;
301             my ( $name, %args ) = @_;
302 2 50       11848 $class->install_symmethod( $target, $name, %args );
303 2         10 return;
304 2 50       4 };
  2 50       10  
305 2         87823 }
306              
307             1;
308              
309 10     10   26667  
310             =pod
311 10         42  
312 10 50       24 =encoding utf-8
313              
314             =head1 NAME
315 14 100   14   2638  
316 14         40 Sub::SymMethod - symbiotic methods; methods that act a little like BUILD and DEMOLISH
317 14         48  
318 14         36 =head1 SYNOPSIS
319 10         66  
320             use strict;
321             use warnings;
322             use feature 'say';
323            
324             {
325             package Local::Base;
326             use Class::Tiny;
327             use Sub::SymMethod;
328            
329             symmethod foo => sub { say __PACKAGE__ };
330             }
331            
332             {
333             package Local::Role;
334             use Role::Tiny;
335             use Sub::SymMethod;
336            
337             symmethod foo => sub { say __PACKAGE__ };
338             }
339            
340             {
341             package Local::Derived;
342             use parent -norequire, 'Local::Base';
343             use Role::Tiny::With; with 'Local::Role';
344             use Sub::SymMethod;
345            
346             symmethod foo => sub { say __PACKAGE__ };
347             }
348            
349             'Local::Derived'->foo();
350             # Local::Base
351             # Local::Role
352             # Local::Derived
353              
354             =head1 DESCRIPTION
355              
356             Sub::SymMethod creates hierarchies of methods so that when you call one,
357             all the methods in the inheritance chain (including ones defined in roles)
358             are invoked.
359              
360             They are invoked from the most basal class to the most derived class.
361             Methods defined in roles are invoked before methods defined in the class
362             they were composed into.
363              
364             This is similar to how the C<BUILD> and C<DEMOLISH> methods are invoked
365             in L<Moo>, L<Moose>, and L<Mouse>. (You should I<not> use this module to
366             define C<BUILD> and C<DEMOLISH> methods though, as Moo/Moose/Mouse already
367             includes all the plumbing to ensure that they are called correctly. This
368             module is instead intended to allow you to define your own methods which
369             behave similarly.)
370              
371             You can think of "symmethod" as being short for "symbiotic method",
372             "syncretic method", or "synarchy of methods".
373              
374             If you are familiar with L<multi methods|Sub::MultiMethod>, you can think
375             of a symmethod as a multi method where instead of picking one "winning"
376             candidate to dispatch to, the dispatcher dispatches to as many candidates
377             as it can find!
378              
379             =head2 Use Cases
380              
381             Symmethods are useful for "hooks". For example, the following pseudocode:
382              
383             class Message {
384             method send () {
385             $self->on_send();
386             $self->do_smtp_stuff();
387             }
388            
389             symmethod on_send () {
390             # do nothing
391             }
392             }
393            
394             role LoggedMessage {
395             symmethod on_send () {
396             print STDERR "Sending message\n";
397             }
398             }
399            
400             class ImportantMessage {
401             extends Message;
402             with LoggedMessage;
403            
404             symmethod on_send () {
405             $self->add_to_archive( "Important" );
406             }
407             }
408              
409             When the C<send> method gets called on an ImportantMessage object, the
410             inherited C<send> method from Message will get invoked. This will call
411             C<on_send>, which will call every C<on_send> definition in the inheritance
412             hierarchy for ImportantMessage, ensuring the sending of the important
413             message gets logged to STDERR and the message gets archived.
414              
415             =head2 Functions
416              
417             Sub::SymMethod exports one function, but which may be called in two
418             different ways.
419              
420             =over
421              
422             =item C<< symmethod $name => $coderef >>
423              
424             Creates a symmethod.
425              
426             =item C<< symmethod $name => %spec >>
427              
428             Creates a symmethod.
429              
430             The specification hash must contain a C<code> key, which must be a coderef.
431             It may also include an C<order> key, which must be numeric. Any other
432             keys are passed to C<signature> from L<Type::Params> to build a signature for
433             the symmethod.
434              
435             =back
436              
437             =head2 Invoking Symmethods
438              
439             Given the following pseudocode:
440              
441             class Base {
442             symmethod foo () {
443             say wantarray ? "List context" : "Scalar context";
444             return "BASE";
445             }
446             }
447            
448             class Derived {
449             extends Base;
450            
451             symmethod foo () {
452             say wantarray ? "List context" : "Scalar context";
453             return "DERIVED";
454             }
455             }
456            
457             my @r = Derived->foo();
458             my $r = Derived->foo();
459              
460             "Scalar context" will be said four times. Symmethods are always invoked in
461             scalar context even when they have been called in list context!
462              
463             The C<< @r >> array will be C<< ( "BASE", "DERIVED" ) >>. When a symmethod
464             is called in list context, a list of the returned values will be returned.
465              
466             The variable C<< $r >> will be C<< 2 >>. It is the count of the returned
467             values.
468              
469             If a symmethod throws an exception this will not be caught, so any further
470             symmethods waiting to be invoked will not get invoked.
471              
472             =head3 Invocation Order
473              
474             It is possible to force a symmethod to run early by setting C<order> to
475             a negative number.
476              
477             symmethod foo => (
478             order => -100,
479             code => sub { my $self = shift; ... },
480             );
481              
482             It is possible to force a symmethod to run late by setting order to a
483             positive number.
484              
485             symmethod foo => (
486             order => 100,
487             code => sub { my $self = shift; ... },
488             );
489              
490             The default C<order> is 0 for all symmethods, and in most cases this will
491             be fine.
492              
493             Where symmethods have the same order (the usual case!) symmethods are invoked
494             from most basal class to most derived class -- i.e. from parent to child.
495             Where a class consumes symmethods from roles, a symmethods defined in a role
496             will be invoked before a symmethod defined in the class, but after any
497             inherited from base/parent classes.
498              
499             =head2 Symmethods and Signatures
500              
501             When defining symmethods, you can define a signature using the same
502             options supported by C<signature> from L<Type::Params>.
503              
504             use Types::Standard 'Num';
505             use Sub::SymMethod;
506            
507             symmethod foo => (
508             positional => [ Num ],
509             code => sub {
510             my ( $self, $num ) = @_;
511             print $num, "\n";
512             },
513             );
514            
515             symmethod foo => (
516             named => [ mynum => Num ],
517             code => sub {
518             my ( $self, $arg ) = @_;
519             print $arg->mynum, "\n";
520             },
521             );
522              
523             When the symmethod is called, any symmethods where the arguments do not match
524             the signature are simply skipped.
525              
526             The invocant ($self or $class or whatever) is I<not> included in the
527             signature.
528              
529             The coderef given in C<code> receives the list of arguments I<after> they've
530             been passed through the signature, which may coerce them, etc.
531              
532             Using a signature requires L<Type::Params> to be installed.
533              
534             =head2 API
535              
536             Sub::SymMethod has an object oriented API for metaprogramming.
537              
538             When describing it, we'll borrow the terms I<dispatcher> and I<candidate>
539             from L<Sub::MultiMethod>. The candidates are the coderefs you gave to
540             Sub::SymMethod -- so there might be a candidate defined in your parent
541             class and a candidate defined in your child class. The dispatcher is the
542             method that Sub::SymMethod creates for you (probably just in the base
543             class, but theoretically perhaps also in the child class) which is responsible
544             for finding the candidates and calling them.
545              
546             The Sub::SymMethod API offers the following methods:
547              
548             =over
549              
550             =item C<< install_symmethod( $target, $name, %spec ) >>
551              
552             Installs a candidate method for a class or role.
553              
554             C<< $target >> is the class or role the candidate is being defined for.
555             C<< $name >> is the name of the method. C<< %spec >> must include a
556             C<code> key and optionally an C<order> key. Any keys not directly supported
557             by Sub::SymMethod will be passed through to Type::Params to provide a
558             signature for the method.
559              
560             If C<< $target >> is a class, this will also install a dispatcher into
561             the class. Passing C<< no_dispatcher => 1 >> in the spec will avoid this.
562              
563             If C<< $target >> is a role, this will also install hooks to the role to
564             notify Sub::SymMethod whenever the role gets consumed by a class. Passing
565             C<< no_hooks => 1 >> in the spec will avoid this.
566              
567             This will also perform any needed cache invalidation.
568              
569             =item C<< build_dispatcher( $target, $name ) >>
570              
571             Builds a coderef that could potentially be installed into
572             C<< *{"$target\::$name"} >> to be used as a dispatcher.
573              
574             =item C<< install_dispatcher( $target, $name ) >>
575              
576             Builds a coderef that could potentially be installed into
577             C<< *{"$target\::$name"} >> to be used as a dispatcher, and
578             actually installs it.
579              
580             This complains if it notices it's overwriting an existing
581             method which isn't a dispatcher. (It also remembers the coderef
582             being installed is a dispatcher, which can later be checked
583             using C<is_dispatcher>.)
584              
585             =item C<< is_dispatcher( $coderef ) >>
586              
587             Checks to see if C<< $coderef >> is a dispatcher.
588              
589             Can also be called as C<< is_dispatcher( $coderef, 0 ) >> or
590             C<< is_dispatcher( $coderef, 1 ) >> to teach it about a coderef.
591              
592             =item C<< dispatch( $invocant, $name, @args ) >>
593              
594             Equivalent to calling C<< $invocant->$name(@args) >> except doesn't use
595             the dispatcher installed into the invocant's class, instead building a
596             new dispatcher and using that.
597              
598             =item C<< install_hooks( $rolename ) >>
599              
600             Given a role, sets up the required hooks which ensure that when the role
601             is composed with a class, dispatchers will be installed into the class to
602             handle all of the role's symmethods, and Sub::SymMethod will know that the
603             class consumed the role.
604              
605             Also performs cache invalidation.
606              
607             =item C<< get_roles_for_class ( $classname ) >>
608              
609             Returns an arrayref containing a list of roles the class is known to
610             consume. We only care about roles that define symmethods.
611              
612             If you need to manually specify that a class consumes a role, you can
613             push the role name onto the arrayref. This would usually only be necessary
614             if you were using an unsupported role implementation. (Supported role
615             implementations include L<Role::Tiny>, L<Role::Basic>, L<Moo::Role>,
616             L<Moose::Role>, and L<Mouse::Role>.)
617              
618             =item C<< clear_cache( $name ) >>
619              
620             Clears all caches associated with any symmethods with a given name.
621             The target class is irrelevent because symmethods can be created in
622             roles which may be consumed by multiple unrelated classes.
623              
624             =item C<< get_symmethod_names( $target ) >>
625              
626             For a given class or role, returns a list of the names of symmethods defined
627             directly in that class or role, not considering inheritance and composition.
628              
629             =item C<< get_symmethods( $target, $name ) >>
630              
631             For a given class or role and a method name, returns an arrayref of spec
632             hashrefs for that symmethod, not considering inheritance and composition.
633              
634             This arrayref can be pushed onto to define more candidates, though this
635             bypasses setting up hooks, installing dispatches, and performing cache
636             invalidation, so C<install_symmethod> is generally preferred unless you're
637             doing something unusual.
638              
639             =item C<< get_all_symmethods( $target, $name ) >>
640              
641             Like C<get_symmethods>, but I<does> consider inheritance and composition.
642             Returns the arrayref of the spec hashrefs in the order they will be called
643             when dispatching.
644              
645             =item C<< compile_signature( \%spec ) >>
646              
647             Does the job of finding keys within the spec to compile into a signature.
648              
649             =item C<< _generate_symmethod( $name, \%opts, \%globalopts ) >>
650              
651             This method is used by C<import> to generate a coderef that will be installed
652             into the called as C<symmethod>.
653              
654             =back
655              
656             =head1 BUGS
657              
658             Please report any bugs to
659             L<https://github.com/tobyink/p5-sub-symmethod/issues>.
660              
661             =head1 SEE ALSO
662              
663             L<Sub::MultiMethod>, L<Type::Params>, L<NEXT>.
664              
665             =head1 AUTHOR
666              
667             Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
668              
669             =head1 COPYRIGHT AND LICENCE
670              
671             This software is copyright (c) 2020, 2022 by Toby Inkster.
672              
673             This is free software; you can redistribute it and/or modify it under
674             the same terms as the Perl 5 programming language system itself.
675              
676             =head1 DISCLAIMER OF WARRANTIES
677              
678             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
679             WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
680             MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.