Commit | Line | Data |
aa2d2e2c |
1 | #include "mouse.h" |
2 | |
0aad0266 |
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 | |
aa2d2e2c |
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 | |