Implement XS accessor generators
[gitmo/Mouse.git] / xs-src / Mouse.xs
1 #include "mouse.h"
2
3 SV* mouse_package;
4 SV* mouse_namespace;
5
6 MODULE = Mouse  PACKAGE = Mouse::Util
7
8 PROTOTYPES: DISABLE
9
10 BOOT:
11     mouse_package   = newSVpvs_share("package");
12     mouse_namespace = newSVpvs_share("namespace");
13
14
15 bool
16 is_class_loaded(SV* sv = &PL_sv_undef)
17
18 void
19 get_code_info(CV* code)
20 PREINIT:
21     GV* gv;
22     HV* stash;
23 PPCODE:
24     if((gv = CvGV(code)) && isGV(gv) && (stash = GvSTASH(gv))){
25         EXTEND(SP, 2);
26         mPUSHs(newSVpvn_share(HvNAME_get(stash), HvNAMELEN_get(stash), 0U));
27         mPUSHs(newSVpvn_share(GvNAME_get(gv), GvNAMELEN_get(gv), 0U));
28     }
29
30 SV*
31 get_code_package(CV* code)
32 PREINIT:
33     HV* stash;
34 CODE:
35     if(CvGV(code) && isGV(CvGV(code)) && (stash = GvSTASH(CvGV(code)))){
36         RETVAL = newSVpvn_share(HvNAME_get(stash), HvNAMELEN_get(stash), 0U);
37     }
38     else{
39         RETVAL = &PL_sv_no;
40     }
41 OUTPUT:
42     RETVAL
43
44 CV*
45 get_code_ref(SV* package, SV* name)
46 CODE:
47 {
48     HV* stash;
49     HE* he;
50
51     if(!SvOK(package)){
52         croak("You must define a package name");
53     }
54     if(!SvOK(name)){
55         croak("You must define a subroutine name");
56     }
57
58     stash = gv_stashsv(package, FALSE);
59     if(!stash){
60         XSRETURN_UNDEF;
61     }
62     he = hv_fetch_ent(stash, name, FALSE, 0U);
63     if(he){
64         GV* const gv = (GV*)hv_iterval(stash, he);
65         if(!isGV(gv)){ /* special constant or stub */
66             STRLEN len;
67             const char* const pv = SvPV_const(name, len);
68             gv_init(gv, stash, pv, len, GV_ADDMULTI);
69         }
70         RETVAL = GvCVu(gv);
71     }
72     else{
73         RETVAL = NULL;
74     }
75
76     if(!RETVAL){
77         XSRETURN_UNDEF;
78     }
79 }
80 OUTPUT:
81     RETVAL
82
83
84 MODULE = Mouse  PACKAGE = Mouse::Util::TypeConstraints
85
86 void
87 Item(SV* sv = &PL_sv_undef)
88 ALIAS:
89     Any        = MOUSE_TC_ANY
90     Item       = MOUSE_TC_ITEM
91     Undef      = MOUSE_TC_UNDEF
92     Defined    = MOUSE_TC_DEFINED
93     Bool       = MOUSE_TC_BOOL
94     Value      = MOUSE_TC_VALUE
95     Ref        = MOUSE_TC_REF
96     Str        = MOUSE_TC_STR
97     Num        = MOUSE_TC_NUM
98     Int        = MOUSE_TC_INT
99     ScalarRef  = MOUSE_TC_SCALAR_REF
100     ArrayRef   = MOUSE_TC_ARRAY_REF
101     HashRef    = MOUSE_TC_HASH_REF
102     CodeRef    = MOUSE_TC_CODE_REF
103     GlobRef    = MOUSE_TC_GLOB_REF
104     FileHandle = MOUSE_TC_FILEHANDLE
105     RegexpRef  = MOUSE_TC_REGEXP_REF
106     Object     = MOUSE_TC_OBJECT
107     ClassName  = MOUSE_TC_CLASS_NAME
108     RoleName   = MOUSE_TC_ROLE_NAME
109 CODE:
110     SvGETMAGIC(sv);
111     ST(0) = boolSV( mouse_tc_check(aTHX_ ix, sv) );
112     XSRETURN(1);
113
114
115 MODULE = Mouse  PACKAGE = Mouse::Meta::Module
116
117 BOOT:
118     INSTALL_SIMPLE_READER_WITH_KEY(Module, name, package);
119     INSTALL_SIMPLE_READER_WITH_KEY(Module, _method_map, methods);
120     INSTALL_SIMPLE_READER_WITH_KEY(Module, _attribute_map, attributes);
121
122 HV*
123 namespace(SV* self)
124 CODE:
125 {
126     SV* const package = mouse_instance_get_slot(self, mouse_package);
127     if(!(package && SvOK(package))){
128         croak("No package name");
129     }
130     RETVAL = gv_stashsv(package, GV_ADDMULTI);
131 }
132 OUTPUT:
133     RETVAL
134
135 MODULE = Mouse  PACKAGE = Mouse::Meta::Class
136
137 BOOT:
138     INSTALL_SIMPLE_READER(Class, roles);
139     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Class, is_anon_class, anon_serial_id);
140
141 void
142 linearized_isa(SV* self)
143 PPCODE:
144 {
145     SV* const stash_ref = mcall0(self, mouse_namespace); /* $self->namespace */
146     AV* linearized_isa;
147     I32 len;
148     I32 i;
149     if(!(SvROK(stash_ref) && SvTYPE(SvRV(stash_ref)) == SVt_PVHV)){
150         croak("namespace() didn't return a HASH reference");
151     }
152     linearized_isa = mro_get_linear_isa((HV*)SvRV(stash_ref));
153     len = AvFILLp(linearized_isa) + 1;
154     EXTEND(SP, len);
155     for(i = 0; i < len; i++){
156         PUSHs(AvARRAY(linearized_isa)[i]);
157     }
158 }
159
160 MODULE = Mouse  PACKAGE = Mouse::Meta::Role
161
162 BOOT:
163     INSTALL_SIMPLE_READER_WITH_KEY(Role, get_roles, roles);
164     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Role, is_anon_role, anon_serial_id);
165
166 MODULE = Mouse  PACKAGE = Mouse::Meta::Attribute
167
168 BOOT:
169     /* readers */
170     INSTALL_SIMPLE_READER(Attribute, name);
171     INSTALL_SIMPLE_READER(Attribute, associated_class);
172     INSTALL_SIMPLE_READER(Attribute, accessor);
173     INSTALL_SIMPLE_READER(Attribute, reader);
174     INSTALL_SIMPLE_READER(Attribute, writer);
175     INSTALL_SIMPLE_READER(Attribute, predicate);
176     INSTALL_SIMPLE_READER(Attribute, clearer);
177     INSTALL_SIMPLE_READER(Attribute, handles);
178
179     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, _is_metadata, is);
180     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_required, required);
181     INSTALL_SIMPLE_READER(Attribute, default);
182     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_lazy, lazy);
183     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_lazy_build, lazy_build);
184     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_weak_ref, weak_ref);
185     INSTALL_SIMPLE_READER(Attribute, init_arg);
186     INSTALL_SIMPLE_READER(Attribute, type_constraint);
187     INSTALL_SIMPLE_READER(Attribute, trigger);
188     INSTALL_SIMPLE_READER(Attribute, builder);
189     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, should_auto_deref, auto_deref);
190     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, should_coerce, coerce);
191     INSTALL_SIMPLE_READER(Attribute, documentation);
192
193     /* predicates */
194     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_accessor, accessor);
195     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_reader, reader);
196     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_writer, writer);
197     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_predicate, predicate);
198     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_clearer, clearer);
199     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_handles, handles);
200
201     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_default, default);
202     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_type_constraint, type_constraint);
203     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_trigger, trigger);
204     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_builder, builder);
205     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_documentation, documentation);
206
207     newCONSTSUB(gv_stashpvs("Mouse::Meta::Attribute", TRUE), "accessor_metaclass",
208         newSVpvs("Mouse::Meta::Method::Accessor::XS"));
209
210 MODULE = Mouse  PACKAGE = Mouse::Meta::TypeConstraint
211
212 BOOT:
213     INSTALL_SIMPLE_READER(TypeConstraint, name);
214     INSTALL_SIMPLE_READER(TypeConstraint, parent);
215     INSTALL_SIMPLE_READER(TypeConstraint, message);
216
217     INSTALL_SIMPLE_READER_WITH_KEY(TypeConstraint, _compiled_type_constraint, compiled_type_constraint);
218     INSTALL_SIMPLE_READER(TypeConstraint, _compiled_type_coercion); /* Mouse specific */
219
220     INSTALL_SIMPLE_PREDICATE_WITH_KEY(TypeConstraint, has_coercion, _compiled_type_coercion);
221
222
223 MODULE = Mouse  PACKAGE = Mouse::Meta::Method::Accessor::XS
224
225 BOOT:
226 {
227     AV* const isa = get_av("Mouse::Meta::Method::Accessor::XS::ISA", TRUE);
228     av_push(isa, newSVpvs("Mouse::Meta::Method::Accessor"));
229 }
230
231 CV*
232 _generate_accessor(klass, SV* attr, metaclass)
233 CODE:
234 {
235     RETVAL = mouse_instantiate_xs_accessor(aTHX_ attr, mouse_xs_accessor);
236 }
237 OUTPUT:
238     RETVAL
239
240 CV*
241 _generate_reader(klass, SV* attr, metaclass)
242 CODE:
243 {
244     RETVAL = mouse_instantiate_xs_accessor(aTHX_ attr, mouse_xs_reader);
245 }
246 OUTPUT:
247     RETVAL
248
249 CV*
250 _generate_writer(klass, SV* attr, metaclass)
251 CODE:
252 {
253     RETVAL = mouse_instantiate_xs_accessor(aTHX_ attr, mouse_xs_writer);
254 }
255 OUTPUT:
256     RETVAL
257
258 CV*
259 _generate_clearer(klass, SV* attr, metaclass)
260 CODE:
261 {
262     SV* const slot = mcall0s(attr, "name");
263     STRLEN len;
264     const char* const pv = SvPV_const(slot, len);
265     RETVAL = mouse_install_simple_accessor(aTHX_ NULL, pv, len, mouse_xs_simple_clearer);
266 }
267 OUTPUT:
268     RETVAL
269
270 CV*
271 _generate_predicate(klass, SV* attr, metaclass)
272 CODE:
273 {
274     SV* const slot = mcall0s(attr, "name");
275     STRLEN len;
276     const char* const pv = SvPV_const(slot, len);
277     RETVAL = mouse_install_simple_accessor(aTHX_ NULL, pv, len, mouse_xs_simple_predicate);
278 }
279 OUTPUT:
280     RETVAL
281