5 #define SLOT_WEAKEN 0x01
8 * needs to be made into Moose::XS::Meta::Instance and Meta::Slot for the
9 * metadata, with a proper destructor. XSANY still points to this struct, but
10 * it is shared by all functions of the same type.
12 * Instance contains SvSTASH, and SLOT slots[]
14 * On recreation of the meta instance we refresh the SLOT value of all the CVs
17 * need a good way to handle time between invalidate and regeneration (just
18 * check XSANY and call get_meta_instance if null?)
23 * slot access is one of 4 values in flags:
26 * 3 == fptr (allows access into C structs, etc)
27 * 4 == callsv (really a special case of fptr)
29 * for fptr case we have a pointer to a vtable for get/set/has/delete, all of which take the same args as set_slot_value
33 * type constraints are already implemented by konobi
34 * should be trivial to do coercions for the core types, too
36 * TypeConstraint::Class can compare SvSTASH by ptr, and if it's neq *then*
37 * call ->isa (should handle vast majority of cases)
39 * base parametrized types are also trivial
41 * ClassName is get_stathpvn
45 * for a constructor we have SLOT *slots, and iterate that, removing init_arg
46 * we can preallocate the structure to the right size (maybe even with the
47 * right HEs?), and do various other prehashing hacks to gain speed
51 * delegations and attribute helpers:
60 * I32 *type; // hash, array, whatever + vtable for operation
67 U32 flags /* slot type, TC behavior, coerce, weaken, (no default | default, builder + lazy), auto_deref */
69 * type constraint (pointer or enum union)
70 * default / builder ptr (or SV *)
75 #define dSLOT SLOT *slot = INT2PTR(SLOT *, XSANY.any_i32)
77 /* utility functions */
79 STATIC SLOT *new_slot_from_key (SV *key, U32 flags) {
80 SLOT *slot = (SLOT *)malloc(sizeof(SLOT));
83 char *pv = SvPV(key, len);
85 PERL_HASH(hash, pv, len);
86 slot->sv = newSVpvn_share(pv, len, hash);
93 STATIC void weaken(SV *sv) {
97 croak("weak references are not implemented in this release of perl");
102 /* meta instance protocol */
104 STATIC SV *get_slot_value(SV *self, SLOT *slot) {
109 assert(SvTYPE(SvRV(self)) == SVt_PVHV);
111 if (he = hv_fetch_ent((HV *)SvRV(self), slot->sv, 0, slot->hash))
117 STATIC void set_slot_value(SV *self, SLOT *slot, SV *value) {
122 assert(SvTYPE(SvRV(self)) == SVt_PVHV);
126 he = hv_store_ent((HV*)SvRV(self), slot->sv, value, slot->hash);
128 if ( slot->flags & SLOT_WEAKEN )
131 croak("Hash store failed.");
135 STATIC bool has_slot_value(SV *self, SLOT *slot) {
138 assert(SvTYPE(SvRV(self)) == SVt_PVHV);
140 return hv_exists_ent((HV *)SvRV(self), slot->sv, slot->hash);
144 /* simple high level api */
146 STATIC XS(simple_getter);
147 STATIC XS(simple_getter)
157 Perl_croak(aTHX_ "Usage: %s(%s)", GvNAME(CvGV(cv)), "self");
161 value = get_slot_value(ST(0), slot);
164 ST(0) = sv_mortalcopy(value); /* mortalcopy because $_ .= "blah" for $foo->bar */
171 STATIC XS(simple_setter);
172 STATIC XS(simple_setter)
181 Perl_croak(aTHX_ "Usage: %s(%s, %s)", GvNAME(CvGV(cv)), "self", "value");
185 set_slot_value(ST(0), slot, ST(1));
187 ST(0) = ST(1); /* return value */
191 STATIC XS(simple_accessor);
192 STATIC XS(simple_accessor)
201 Perl_croak(aTHX_ "Usage: %s(%s, [ %s ])", GvNAME(CvGV(cv)), "self", "value");
206 set_slot_value(ST(0), slot, ST(1));
207 ST(0) = ST(1); /* return value */
209 SV *value = get_slot_value(ST(0), slot);
220 STATIC XS(predicate);
230 Perl_croak(aTHX_ "Usage: %s(%s)", GvNAME(CvGV(cv)), "self");
234 if ( has_slot_value(ST(0), slot) )
241 xs_body_simple_getter = 0,
242 xs_body_simple_setter,
243 xs_body_simple_accessor,
248 STATIC XSPROTO ((*xs_bodies[])) = {
255 MODULE = Moose PACKAGE = Moose::XS
258 install_sub(name, key)
263 install_simple_getter = xs_body_simple_getter
264 install_simple_setter = xs_body_simple_setter
265 install_simple_accessor = xs_body_simple_accessor
266 install_predicate = xs_body_predicate
270 if ( ix >= max_xs_body )
271 croak("Unknown Moose::XS body type");
273 cv = newXS(name, xs_bodies[ix], __FILE__);
278 /* FIXME leaks, fail for anon classes */
279 XSANY.any_i32 = PTR2IV(new_slot_from_key(key, 0));