package Data::Dumper::ToXS;
-our (%ix, %seen, $weaken);
+our (%ix, %seen, $postamble, %stash);
sub _newix { $_[0].'['.($ix{$_[0]}++).']' }
sub _getglob { \*{$_[0]} }
use B qw(svref_2object cstring);
-use Scalar::Util qw(refaddr isweak);
+use Scalar::Util qw(refaddr isweak blessed reftype);
use Moo;
has target_package => (is => 'ro', required => 1);
sub add_generator {
my ($self, $name, $ref) = @_;
- die "Generation target must be a reference" unless ref($ref);
+ die "Generation target ${\($ref||'undef')} for ${\($name||'undef')} must be a reference" unless ref($ref);
push(@{$self->_to_generate}, [ $name => $ref ]);
}
my ($self, $name, $ref) = @_;
local %ix = map +($_ => 0), qw(av hv sv);
local %seen;
- local $weaken = '';
+ local $postamble = '';
+ local %stash;
my $first = _newix('sv');
my $body = $self->_dump_svrv($first, $ref);
my $vars = join '', map +(
<<"END";
SV * ${name} (pTHX)
{
-${vars}${body}${weaken} return ${first};
+${vars}${body}${postamble} return ${first};
}
END
}
sub _dump_svrv {
my ($self, $ix, $ref) = @_;
- my $r = ref($ref);
- $weaken .= " sv_rvweaken(${ix});\n" if isweak($_[2]);
+ my $r = reftype($ref);
+ $postamble .= " sv_rvweaken(${ix});\n" if isweak($_[2]);
if ($seen{$ref}) {
# already seen this reference so make a copy
" ${ix} = newSVsv($seen{$ref});\n";
} else {
$seen{$ref} = $ix;
+ if (my $class = blessed($ref)) {
+ my $s_ix = $stash{$class} ||= do {
+ my $s_ix = _newix('hv');
+ $postamble .= " ${s_ix} = gv_stashpvs(${\cstring $class}, GV_ADD);\n";
+ $s_ix;
+ };
+ $postamble .=
+ " sv_bless(${ix}, ${s_ix});\n";
+ }
if ($r eq 'SCALAR') {
my $t_ix = _newix('sv');
join '',