*
* These functions return mortal copiess and save copies (handling refcounting). */
-STATIC void attr_set_value(pTHX_ SV *self, ATTR *attr, SV *value);
+STATIC void attr_set_common(pTHX_ SV *self, ATTR *attr, SV *value) {
+ SV *copy;
+
+ if ( !value ) {
+ /* FIXME croak if required ? */
+ return;
+ }
+
+ if ( ATTR_TYPE(attr) ) {
+ if ( !check_type_constraint(aTHX_ ATTR_TYPE(attr), attr->tc_check, attr->type_constraint, value) )
+ croak("Bad param");
+ }
+
+ copy = newSVsv(value);
+
+ if ( ATTR_ISWEAK(attr) && SvROK(copy) )
+ weaken(aTHX_ copy);
+
+ if ( !set_slot_value(aTHX_ self, attr, copy) ) {
+ SvREFCNT_dec(copy);
+ croak("Hash store failed.");
+ }
+}
+
+STATIC void attr_set_initial_value(pTHX_ SV *self, ATTR *attr, SV *value) {
+ if ( attr->initializer ) {
+ croak("todo");
+ } else {
+ attr_set_common(aTHX_ self, attr, value);
+ }
+}
STATIC SV *call_builder (pTHX_ SV *self, ATTR *attr) {
SV *sv;
return sv_mortalcopy(value);
} else if ( ATTR_ISLAZY(attr) ) {
value = get_default(aTHX_ self, attr);
- attr_set_value(aTHX_ self, attr, value);
+ attr_set_initial_value(aTHX_ self, attr, value);
return value;
}
/* $attr->set_value($self) */
STATIC void attr_set_value(pTHX_ SV *self, ATTR *attr, SV *value) {
- SV *copy;
+ attr_set_common(aTHX_ self, attr, value);
- if ( !value ) {
- /* FIXME croak if required ? */
- return;
- }
+ if ( attr->trigger ) {
+ dSP;
- if ( ATTR_TYPE(attr) ) {
- if ( !check_type_constraint(aTHX_ ATTR_TYPE(attr), attr->tc_check, attr->type_constraint, value) )
- croak("Bad param");
- }
+ ENTER;
+ SAVETMPS;
+ PUSHMARK(SP);
- copy = newSVsv(value);
+ /* FIXME copy self & meta attr? */
+ XPUSHs(self);
+ XPUSHs(sv_2mortal(newSVsv(value)));
+ XPUSHs(attr->meta_attr);
- if ( ATTR_ISWEAK(attr) && SvROK(copy) )
- weaken(aTHX_ copy);
+ /* we invoke the builder as a stringified method. This will not work for
+ * $obj->$coderef etc, for that we need to use 'default' */
+ PUTBACK;
+ call_method(SvPV_nolen(attr->def.sv), G_VOID);
- if ( !set_slot_value(aTHX_ self, attr, copy) ) {
- SvREFCNT_dec(copy);
- croak("Hash store failed.");
+ FREETMPS;
+ LEAVE;
}
}
plan 'no_plan';
}
+my $i;
+
{
package Moose::XS;
has c => ( isa => "ClassName", is => "rw" );
has b => ( is => "ro", lazy_build => 1 ); # fixme type constraint checking
has tc => ( is => "rw", isa => "FiveChars" );
+ has t => ( is => "rw", trigger => sub { $i++ } );
sub _build_b { "builded!" }
}
{
- my ( $x, $y, $z, $ref, $a, $s, $i, $o, $f, $c, $b ) = map { Foo->meta->get_attribute($_) } qw(x y z ref a s i o f c b);
+ my ( $x, $y, $z, $ref, $a, $s, $i, $o, $f, $c, $b, $tc, $t ) = map { Foo->meta->get_attribute($_) } qw(x y z ref a s i o f c b tc t);
$x->Moose::XS::new_accessor("Foo::x");
$x->Moose::XS::new_predicate("Foo::has_x");
$y->Moose::XS::new_reader("Foo::y");
$f->Moose::XS::new_accessor("Foo::f");
$c->Moose::XS::new_accessor("Foo::c");
$b->Moose::XS::new_accessor("Foo::b");
+ $tc->Moose::XS::new_accessor("Foo::tc");
+ $t->Moose::XS::new_accessor("Foo::t");
}
undef $ref;
is( $foo->ref(), undef, "weak ref destroyed" );
+is( $i, undef, "trigger not yet called" );
+is( $foo->t, undef, "no value in t" );
+is( $i, undef, "trigger not yet called" );
+
ok( !eval { $foo->a("not a ref"); 1 }, "ArrayRef" );
ok( !eval { $foo->a(3); 1 }, "ArrayRef" );
ok( !eval { $foo->a({}); 1 }, "ArrayRef" );