# -*- mode: perl; coding: utf-8 -*- package YATT::Fields; use strict; use warnings FATAL => qw(all); use YATT::Util::Symbol; sub import { require fields; my ($thispack) = shift; my ($callpack) = caller; my @public; my @setter; my @FIELDS; foreach my $desc (@_) { my ($slot, $default); if (ref $desc) { $slot = shift @$desc; $default = do { if (@$desc > 1) { sub { wantarray ? @$desc : [@$desc]; }; } elsif (! @$desc) { undef; } elsif (ref(my $value = $desc->[0]) eq 'CODE') { $value; } else { sub () { $value; } } }; } else { $slot = $desc; } if ($slot =~ s/^([\^=]+)((?:cf_)?)//) { my $func_name = $slot; my $cf_slot = "$2$slot"; foreach my $ch (split //, $1) { push @public, [$func_name, $cf_slot] if $ch eq '^'; push @setter, [$func_name, $cf_slot] if $ch eq '='; } push @FIELDS, $cf_slot; } else { push @FIELDS, $slot; } if (defined $default) { *{globref($callpack, "default_$slot")} = $default; } } my $script = <{%2$s} if defined $self->{%2$s}; return undef unless my $sub = $self->can('default_%1$s'); $self->{%2$s} = $sub->(); } END $script .= join "", map {sprintf <<'END', @$_} @setter; sub set_%s { my MY $self = shift; $self->{%s} = shift; $self; } END eval qq{#line 1 "/dev/null"\n}.$script; die "$@\n$script" if $@; } 1;