9bda4c64ec21a564497bfe6892fc413df075b993
[gitmo/Mouse.git] / xs-src / MouseAttribute.xs
1 #include "mouse.h"
2
3
4 AV*
5 mouse_get_xa(pTHX_ SV* const attr) {
6     static MGVTBL mouse_xa_vtbl; /* identity */
7
8     AV* xa;
9     MAGIC* mg;
10
11     if(!IsObject(attr)){
12         croak("Not a Mouse meta attribute");
13     }
14
15     mg = mouse_mg_find(aTHX_ SvRV(attr), &mouse_xa_vtbl, 0x00);
16     if(!mg){
17         SV* slot;
18         STRLEN len;
19         const char* pv;
20         U16 flags = 0x00;
21
22         ENTER;
23         SAVETMPS;
24
25         xa    = newAV();
26
27         mg = sv_magicext(SvRV(attr), (SV*)xa, PERL_MAGIC_ext, &mouse_xa_vtbl,NULL, 0);
28         SvREFCNT_dec(xa); /* refcnt++ in sv_magicext */
29
30         av_extend(xa, MOUSE_XA_last - 1);
31
32         slot = mcall0(attr, mouse_name);
33         pv = SvPV_const(slot, len);
34         av_store(xa, MOUSE_XA_SLOT, newSVpvn_share(pv, len, 0U));
35
36         av_store(xa, MOUSE_XA_ATTRIBUTE, newSVsv(attr));
37
38         if(predicate_calls(attr, "has_type_constraint")){
39             SV* tc;
40             flags |= MOUSEf_ATTR_HAS_TC;
41
42             tc = mcall0s(attr, "type_constraint");
43             av_store(xa, MOUSE_XA_TC, newSVsv(tc));
44
45             if(predicate_calls(attr, "should_auto_deref")){
46                 SV* const is_a_type_of = sv_2mortal(newSVpvs_share("is_a_type_of"));
47
48                 flags |= MOUSEf_ATTR_SHOULD_AUTO_DEREF;
49                 if( SvTRUEx(mcall1(tc, is_a_type_of, newSVpvs_flags("ArrayRef", SVs_TEMP))) ){
50                     flags |= MOUSEf_TC_IS_ARRAYREF;
51                 }
52                 else if( SvTRUEx(mcall1(tc, is_a_type_of, newSVpvs_flags("HashRef", SVs_TEMP))) ){
53                     flags |= MOUSEf_TC_IS_HASHREF;
54                 }
55                 else{
56                     mouse_throw_error(attr, tc,
57                         "Can not auto de-reference the type constraint '%"SVf"'",
58                             mcall0(tc, mouse_name));
59                 }
60             }
61
62             if(predicate_calls(attr, "should_coerce")){
63                 flags |= MOUSEf_ATTR_SHOULD_COERCE;
64             }
65
66         }
67
68         if(predicate_calls(attr, "has_trigger")){
69             flags |= MOUSEf_ATTR_HAS_TRIGGER;
70         }
71
72         if(predicate_calls(attr, "is_lazy")){
73             flags |= MOUSEf_ATTR_IS_LAZY;
74
75             if(predicate_calls(attr, "has_builder")){
76                 flags |= MOUSEf_ATTR_HAS_BUILDER;
77             }
78             else if(predicate_calls(attr, "has_default")){
79                 flags |= MOUSEf_ATTR_HAS_DEFAULT;
80             }
81         }
82
83         if(predicate_calls(attr, "is_weak_ref")){
84             flags |= MOUSEf_ATTR_IS_WEAK_REF;
85         }
86
87         if(predicate_calls(attr, "is_required")){
88             flags |= MOUSEf_ATTR_IS_REQUIRED;
89         }
90
91         av_store(xa, MOUSE_XA_FLAGS, newSVuv(flags));
92         MOUSE_mg_flags(mg) = flags;
93
94         FREETMPS;
95         LEAVE;
96     }
97     else{
98         xa    = (AV*)MOUSE_mg_obj(mg);
99
100         assert(xa);
101         assert(SvTYPE(xa) == SVt_PVAV);
102     }
103
104     return xa;
105 }
106
107
108 MODULE = Mouse::Meta::Attribute  PACKAGE = Mouse::Meta::Attribute
109
110 PROTOTYPES: DISABLE
111
112 BOOT:
113     /* readers */
114     INSTALL_SIMPLE_READER(Attribute, name);
115     INSTALL_SIMPLE_READER(Attribute, associated_class);
116     INSTALL_SIMPLE_READER(Attribute, accessor);
117     INSTALL_SIMPLE_READER(Attribute, reader);
118     INSTALL_SIMPLE_READER(Attribute, writer);
119     INSTALL_SIMPLE_READER(Attribute, predicate);
120     INSTALL_SIMPLE_READER(Attribute, clearer);
121     INSTALL_SIMPLE_READER(Attribute, handles);
122
123     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, _is_metadata, is);
124     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_required, required);
125     INSTALL_SIMPLE_READER(Attribute, default);
126     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_lazy, lazy);
127     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_lazy_build, lazy_build);
128     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_weak_ref, weak_ref);
129     INSTALL_SIMPLE_READER(Attribute, init_arg);
130     INSTALL_SIMPLE_READER(Attribute, type_constraint);
131     INSTALL_SIMPLE_READER(Attribute, trigger);
132     INSTALL_SIMPLE_READER(Attribute, builder);
133     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, should_auto_deref, auto_deref);
134     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, should_coerce, coerce);
135     INSTALL_SIMPLE_READER(Attribute, documentation);
136
137     /* predicates */
138     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_accessor, accessor);
139     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_reader, reader);
140     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_writer, writer);
141     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_predicate, predicate);
142     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_clearer, clearer);
143     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_handles, handles);
144
145     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_default, default);
146     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_type_constraint, type_constraint);
147     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_trigger, trigger);
148     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_builder, builder);
149     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_documentation, documentation);
150
151     newCONSTSUB(gv_stashpvs("Mouse::Meta::Attribute", TRUE), "accessor_metaclass",
152         newSVpvs("Mouse::Meta::Method::Accessor::XS"));
153