Skip to content

Commit

Permalink
now able to serialize and reconstruct a simple MOP class with an acce…
Browse files Browse the repository at this point in the history
…ssor
  • Loading branch information
shadowcat-mst committed Dec 12, 2008
1 parent 071c63d commit e08f4bf
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 13 deletions.
23 changes: 17 additions & 6 deletions lib/MooseX/Antlers/Recorder.pm
Expand Up @@ -13,6 +13,7 @@ sub new {

sub instrument_routines {
my ($self, @names) = @_;
push(@{$self->{tracked_routines}}, @names);
$self->_instrument_calls(
sub {
my $orig = shift;
Expand Down Expand Up @@ -114,8 +115,8 @@ sub record_coderef_construction {
$self->{buildable}{$coderef} = sub {
my $constructors = $self->{coderef_constructors};
my $val_str = $self->next_values_member;
my $captures_dump = $self->with_custom_dumper_do($captures);
$captures_dump =~ s/^\$VAR1/my \$__captures/;
my $captures_dump = $self->with_custom_dumper_do($captures, '$__captures');
$captures_dump = 'my $__captures; '.$captures_dump;
my $serialise_captures = $self->build_capture_constructor($captures);
push(@$constructors,
q!sub { !
Expand Down Expand Up @@ -187,7 +188,7 @@ sub emit_call_results {

my $dump_sub = q!sub {
!.join("\n", map { "$_->();" } @{$self->{coderef_constructors}}).qq!
my ${final_dump}
my \$VAR1; ${final_dump}; \$VAR1;
}!;
#warn $dump_sub;
return q!my @values;
Expand All @@ -200,15 +201,19 @@ sub emit_call_results {
}

sub with_custom_dumper_do {
my ($self, $value) = @_;
my ($self, $value, $name) = @_;
my $_dump = Data::Dumper->can('_dump');
local $self->{dumper_fixups} = [];
no warnings 'redefine';
local *Data::Dumper::_dump = sub {
$self->dumper_handler($_dump, @_);
};
local $Data::Dumper::Useperl = 1;
local $Data::Dumper::Indent = 1;
Data::Dumper->new([ $value ])->Dump;
$name ||= '$VAR1';
local $self->{dumping_as} = $name;
Data::Dumper->new([ $value ], [ $name ])->Dump
.join("\n", @{$self->{dumper_fixups}});
}

sub dumper_handler {
Expand All @@ -229,7 +234,13 @@ sub dumper_handler {
}
warn "Coderef ${val} not recognised, only superman can save us!";
}
return $_dump->(@_);
my $result = $_dump->(@_);
my $as = $self->{dumping_as};
if ($result =~ /^${\quotemeta $as}/) {
push(@{$self->{dumper_fixups}}, "${name} = ${result};");
return 'undef';
}
return $result;
}

1;
51 changes: 44 additions & 7 deletions t/simple-mop.t
Expand Up @@ -8,19 +8,56 @@ my $ar = MooseX::Antlers::Recorder->new;
$ar->instrument_routines('Class::MOP::Class::add_attribute');
$ar->instrument_sub_constructors('Class::MOP::Method::Generated::_eval_closure');

my $foo_class = Class::MOP::Class->initialize("Foo");
sub setup_class {

$foo_class->add_attribute('one',
name => 'one', reader => 'get_one',
writer => { set_one => sub { shift->{one} = shift } },
);
my $foo_class = Class::MOP::Class->initialize("Foo");

$foo_class->make_immutable;
$foo_class->add_attribute('one',
name => 'one', reader => 'get_one',
writer => { set_one => sub { shift->{one} = shift } },
);

$foo_class->make_immutable;

$foo_class;

}

my $foo_class = setup_class;

use Data::Dumper;
$Data::Dumper::Deparse = 1;
$Data::Dumper::Indent = 1;
$Data::Dumper::Sortkeys = 1;

print Dumper($foo_class);

print $ar->emit_call_results($foo_class);
print "\n---\n";

my $call = $ar->emit_call_results($foo_class);

#warn $call;

my ($save, $final) = eval $call;

die $@ if $@;

undef($foo_class);

Class::MOP::remove_metaclass_by_name("Foo");

{
my $replay = sub { shift(@$save)->(@_) };

no warnings 'redefine';

local *Class::MOP::Class::add_attribute = $replay;

local *Class::MOP::Class::make_immutable = sub {
Class::MOP::store_metaclass_by_name('Foo', $_[0] = $final->());
};

$foo_class = setup_class;
}

print Dumper($foo_class);

0 comments on commit e08f4bf

Please sign in to comment.