Checking in changes prior to tagging of version 0.40_04. Changelog diff is:
[gitmo/Mouse.git] / xs-src / Mouse.xs
1 #include "mouse.h"
2
3 SV* mouse_package;
4 SV* mouse_namespace;
5 SV* mouse_methods;
6 SV* mouse_name;
7
8 MODULE = Mouse  PACKAGE = Mouse
9
10 PROTOTYPES: DISABLE
11
12 BOOT:
13     mouse_package   = newSVpvs_share("package");
14     mouse_namespace = newSVpvs_share("namespace");
15     mouse_methods   = newSVpvs_share("methods");
16     mouse_name      = newSVpvs_share("name");
17
18     MOUSE_CALL_BOOT(Mouse__Util);
19     MOUSE_CALL_BOOT(Mouse__Util__TypeConstraints);
20     MOUSE_CALL_BOOT(Mouse__Meta__Method__Accessor__XS);
21
22
23 MODULE = Mouse  PACKAGE = Mouse::Meta::Module
24
25 BOOT:
26     INSTALL_SIMPLE_READER_WITH_KEY(Module, name, package);
27     INSTALL_SIMPLE_READER_WITH_KEY(Module, _method_map, methods);
28     INSTALL_SIMPLE_READER_WITH_KEY(Module, _attribute_map, attributes);
29
30 HV*
31 namespace(SV* self)
32 CODE:
33 {
34     SV* const package = get_slot(self, mouse_package);
35     if(!(package && SvOK(package))){
36         croak("No package name defined");
37     }
38     RETVAL = gv_stashsv(package, GV_ADDMULTI);
39 }
40 OUTPUT:
41     RETVAL
42
43 # ignore extra arguments for extensibility
44 void
45 add_method(SV* self, SV* name, SV* code, ...)
46 CODE:
47 {
48     SV* const package = get_slot(self, mouse_package); /* $self->{package} */
49     SV* const methods = get_slot(self, mouse_methods); /* $self->{methods} */
50     GV* gv;
51     SV* code_ref;
52
53     if(!(package && SvOK(package))){
54         croak("No package name defined");
55     }
56
57     SvGETMAGIC(name);
58     SvGETMAGIC(code);
59
60     if(!SvOK(name)){
61         mouse_throw_error(self, NULL, "You must define a method name");
62     }
63     if(!SvROK(code)){
64         mouse_throw_error(self, NULL, "You must define a CODE reference");
65     }
66
67     code_ref = code;
68     if(SvTYPE(SvRV(code_ref)) != SVt_PVCV){
69         SV*  sv = code_ref;  /* used in tryAMAGICunDEREF */
70         SV** sp = &sv;       /* used in tryAMAGICunDEREF */
71         tryAMAGICunDEREF(to_cv); /* try \&{$code} */
72         if(SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVCV){
73             mouse_throw_error(self, NULL, "Not a CODE reference");
74         }
75         code_ref = sv;
76     }
77
78     /*  *{$package . '::' . $name} -> *gv */
79     gv = gv_fetchpv(form("%"SVf"::%"SVf, package, name), GV_ADDMULTI, SVt_PVCV);
80     if(GvCVu(gv)){ /* delete *slot{gv} to work around "redefine" warning */
81         SvREFCNT_dec(GvCV(gv));
82         GvCV(gv) = NULL;
83     }
84     sv_setsv_mg((SV*)gv, code_ref); /* *gv = $code_ref */
85
86     set_slot(methods, name, code); /* $self->{methods}{$name} = $code */
87
88     /* TODO: name the CODE ref if it's anonymous */
89     //code_entity = (CV*)SvRV(code_ref);
90     //if(CvANON(code_entity)
91     //    && CvGV(code_entity) /* a cv under construction has no gv */ ){
92
93     //    CvGV(code_entity) = gv;
94     //    CvANON_off(code_entity);
95     //}
96 }
97
98 MODULE = Mouse  PACKAGE = Mouse::Meta::Class
99
100 BOOT:
101     INSTALL_SIMPLE_READER(Class, roles);
102     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Class, is_anon_class, anon_serial_id);
103
104 void
105 linearized_isa(SV* self)
106 PPCODE:
107 {
108     SV* const stash_ref = mcall0(self, mouse_namespace); /* $self->namespace */
109     AV* linearized_isa;
110     I32 len;
111     I32 i;
112     if(!(SvROK(stash_ref) && SvTYPE(SvRV(stash_ref)) == SVt_PVHV)){
113         croak("namespace() didn't return a HASH reference");
114     }
115     linearized_isa = mro_get_linear_isa((HV*)SvRV(stash_ref));
116     len = AvFILLp(linearized_isa) + 1;
117     EXTEND(SP, len);
118     for(i = 0; i < len; i++){
119         PUSHs(AvARRAY(linearized_isa)[i]);
120     }
121 }
122
123
124 MODULE = Mouse  PACKAGE = Mouse::Meta::Role
125
126 BOOT:
127     INSTALL_SIMPLE_READER_WITH_KEY(Role, get_roles, roles);
128     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Role, is_anon_role, anon_serial_id);
129
130 MODULE = Mouse  PACKAGE = Mouse::Meta::Attribute
131
132 BOOT:
133     /* readers */
134     INSTALL_SIMPLE_READER(Attribute, name);
135     INSTALL_SIMPLE_READER(Attribute, associated_class);
136     INSTALL_SIMPLE_READER(Attribute, accessor);
137     INSTALL_SIMPLE_READER(Attribute, reader);
138     INSTALL_SIMPLE_READER(Attribute, writer);
139     INSTALL_SIMPLE_READER(Attribute, predicate);
140     INSTALL_SIMPLE_READER(Attribute, clearer);
141     INSTALL_SIMPLE_READER(Attribute, handles);
142
143     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, _is_metadata, is);
144     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_required, required);
145     INSTALL_SIMPLE_READER(Attribute, default);
146     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_lazy, lazy);
147     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_lazy_build, lazy_build);
148     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_weak_ref, weak_ref);
149     INSTALL_SIMPLE_READER(Attribute, init_arg);
150     INSTALL_SIMPLE_READER(Attribute, type_constraint);
151     INSTALL_SIMPLE_READER(Attribute, trigger);
152     INSTALL_SIMPLE_READER(Attribute, builder);
153     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, should_auto_deref, auto_deref);
154     INSTALL_SIMPLE_READER_WITH_KEY(Attribute, should_coerce, coerce);
155     INSTALL_SIMPLE_READER(Attribute, documentation);
156
157     /* predicates */
158     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_accessor, accessor);
159     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_reader, reader);
160     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_writer, writer);
161     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_predicate, predicate);
162     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_clearer, clearer);
163     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_handles, handles);
164
165     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_default, default);
166     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_type_constraint, type_constraint);
167     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_trigger, trigger);
168     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_builder, builder);
169     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_documentation, documentation);
170
171     newCONSTSUB(gv_stashpvs("Mouse::Meta::Attribute", TRUE), "accessor_metaclass",
172         newSVpvs("Mouse::Meta::Method::Accessor::XS"));
173
174 MODULE = Mouse  PACKAGE = Mouse::Meta::TypeConstraint
175
176 BOOT:
177     INSTALL_SIMPLE_READER(TypeConstraint, name);
178     INSTALL_SIMPLE_READER(TypeConstraint, parent);
179     INSTALL_SIMPLE_READER(TypeConstraint, message);
180
181     INSTALL_SIMPLE_READER_WITH_KEY(TypeConstraint, _compiled_type_constraint, compiled_type_constraint);
182     INSTALL_SIMPLE_READER(TypeConstraint, _compiled_type_coercion); /* Mouse specific */
183
184     INSTALL_SIMPLE_PREDICATE_WITH_KEY(TypeConstraint, has_coercion, _compiled_type_coercion);
185
186