File: ObjectPad.pm

package info (click to toggle)
libsub-handlesvia-perl 0.052000-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,740 kB
  • sloc: perl: 9,645; makefile: 2
file content (104 lines) | stat: -rw-r--r-- 3,080 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use 5.008;
use strict;
use warnings;

package Sub::HandlesVia::Toolkit::ObjectPad;

our $AUTHORITY = 'cpan:TOBYINK';
our $VERSION   = '0.052000';

use Sub::HandlesVia::Mite -all;
extends 'Sub::HandlesVia::Toolkit';

around code_generator_for_attribute => sub {
	my ( $next, $me, $target, $attr ) = ( shift, shift, @_ );
	
	if ( @$attr > 1 or $attr->[0] =~ /^\w/ ) {
		return $me->$next( @_ );
	}
	
	my $attrname = $attr->[0];
	
	use Object::Pad qw( :experimental(mop) );
	use Object::Pad::MetaFunctions ();
	
	my $metaclass = Object::Pad::MOP::Class->for_class($target);
	my $metafield = $metaclass->get_field( $attrname );
	
	my ( $get, $set, $slot, $get_is_lvalue );
	
	if ( $attrname =~ /^\$/ ) {
		
		$get = sub {
			my ( $gen ) = ( shift );
			sprintf( '$metafield->value(%s)', $gen->generate_self );
		};
		$set = sub {
			my ( $gen, $value ) = ( shift, @_ );
			sprintf( '( $metafield->value(%s) = %s )', $gen->generate_self, $value );
		};
		$slot = sub {
			my ( $gen, $value ) = ( shift, @_ );
			sprintf( '${ Object::Pad::MetaFunctions::ref_field(%s, %s) }', B::perlstring($attrname), $gen->generate_self );
		};
		$get_is_lvalue = false;
	}
	elsif ( $attrname =~ /^\@/ ) {
		
		$get = sub {
			my ( $gen ) = ( shift );
			sprintf( 'Object::Pad::MetaFunctions::ref_field(%s, %s)', B::perlstring($attrname), $gen->generate_self );
		};
		$set = sub {
			my ( $gen, $value ) = ( shift, @_ );
			sprintf( '( @{Object::Pad::MetaFunctions::ref_field(%s, %s)} = @{%s} )', B::perlstring($attrname), $gen->generate_self, $value );
		};
		$slot = sub {
			my ( $gen, $value ) = ( shift, @_ );
			sprintf( 'Object::Pad::MetaFunctions::ref_field(%s, %s)', B::perlstring($attrname), $gen->generate_self );
		};
		$get_is_lvalue = true;
	}
	elsif ( $attrname =~ /^\%/ ) {
		
		$get = sub {
			my ( $gen ) = ( shift );
			sprintf( 'Object::Pad::MetaFunctions::ref_field(%s, %s)', B::perlstring($attrname), $gen->generate_self );
		};
		$set = sub {
			my ( $gen, $value ) = ( shift, @_ );
			sprintf( '( %%{Object::Pad::MetaFunctions::ref_field(%s, %s)} = %%{%s} )', B::perlstring($attrname), $gen->generate_self, $value );
		};
		$slot = sub {
			my ( $gen, $value ) = ( shift, @_ );
			sprintf( 'Object::Pad::MetaFunctions::ref_field(%s, %s)', B::perlstring($attrname), $gen->generate_self );
		};
		$get_is_lvalue = true;
	}
	else {
		croak 'Unexpected name for Object::Pad attribute: %s', $attr;
	}
	
	require Sub::HandlesVia::CodeGenerator;
	return 'Sub::HandlesVia::CodeGenerator'->new(
		toolkit               => $me,
		target                => $target,
		attribute             => $attrname,
		env                   => { '$metafield' => \$metafield },
		method_installer      => sub { $metaclass->add_method( @_ ) }, # compile-time!
		coerce                => false,
		generator_for_get     => $get,
		generator_for_set     => $set,
		generator_for_slot    => $slot,
		get_is_lvalue         => $get_is_lvalue,
		set_checks_isa        => true,
		set_strictly          => false,
		generator_for_default => sub {
			my ( $gen, $handler ) = @_ or die;
			return;
		},
	);
};

1;