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