#include "mop.h"
#include "moose.h"
-
-typedef struct {
- U16 flags;
- mop_instance_vtbl* vtbl;
-
- SV* metaclass;
- SV* instance;
- SV* attribute;
-} moose_accessor;
-
-/* Moose Accessor meta information */
-enum meta_ix_t{
- MA_KEY = 0, /* this must be here (see mop.h) */
-
- MA_ACCESSOR,
- MA_CLASS,
- MA_INSTANCE,
- MA_ATTRIBUTE,
- MA_TC,
- MA_TC_CODE,
-
- MA_size
+/* Moose Meta Instance object */
+enum moose_mi_ix_t{
+ MOOSE_MI_ACCESSOR = MOP_MI_last,
+ MOOSE_MI_CLASS,
+ MOOSE_MI_INSTANCE,
+ MOOSE_MI_ATTRIBUTE,
+ MOOSE_MI_TC,
+ MOOSE_MI_TC_CODE,
+
+ MOOSE_MI_last
};
-#ifndef DEBUGGING
-#define MA_of(m, s) (AvARRAY(m)[s])
-#else
-#define MA_of(m, s) *mop_debug_ma_of(aTHX_ m, s)
-static SV**
-mop_debug_ma_of(pTHX_ AV* const meta, enum meta_ix_t const ix){
- assert(meta);
- assert(SvTYPE(meta) == SVt_PVAV);
- assert(AvMAX(meta) >= (I32)ix);
- assert(AvARRAY(meta)[ix]);
- return &AvARRAY(meta)[ix];
-}
-#endif
-
-#define MA_key(m) MA_of(m, MA_KEY)
-#define MA_accessor(m) MA_of(m, MA_ACCESSOR)
-#define MA_class(m) MA_of(m, MA_CLASS)
-#define MA_instance(m) MA_of(m, MA_INSTANCE)
-#define MA_attribute(m) MA_of(m, MA_ATTRIBUTE)
-#define MA_tc(m) MA_of(m, MA_TC)
-#define MA_tc_code(m) MA_of(m, MA_TC_CODE)
+#define MOOSE_mi_slot(m) MOP_mi_slot(m)
+#define MOOSE_mi_accessor(m) MOP_mi_access(m, MOOSE_MI_ACCESSOR)
+#define MOOSE_mi_class(m) MOP_mi_access(m, MOOSE_MI_CLASS)
+#define MOOSE_mi_instance(m) MOP_mi_access(m, MOOSE_MI_INSTANCE)
+#define MOOSE_mi_attribute(m) MOP_mi_access(m, MOOSE_MI_ATTRIBUTE)
+#define MOOSE_mi_tc(m) MOP_mi_access(m, MOOSE_MI_TC)
+#define MOOSE_mi_tc_code(m) MOP_mi_access(m, MOOSE_MI_TC_CODE)
+#define MOOSE_mg_accessor(mg) MOOSE_mi_accessor(MOP_mg_mi(mg))
-enum meta_flags{
- MAf_ATTR_HAS_TC = 0x0001,
- MAf_ATTR_HAS_DEFAULT = 0x0002,
- MAf_ATTR_HAS_BUILDER = 0x0004,
- MAf_ATTR_HAS_INITIALIZER = 0x0008,
- MAf_ATTR_HAS_TRIGGER = 0x0010,
+enum moose_mi_flags_t{
+ MOOSE_MIf_ATTR_HAS_TC = 0x0001,
+ MOOSE_MIf_ATTR_HAS_DEFAULT = 0x0002,
+ MOOSE_MIf_ATTR_HAS_BUILDER = 0x0004,
+ MOOSE_MIf_ATTR_HAS_INITIALIZER = 0x0008,
+ MOOSE_MIf_ATTR_HAS_TRIGGER = 0x0010,
- MAf_ATTR_IS_LAZY = 0x0020,
- MAf_ATTR_IS_WEAK_REF = 0x0040,
- MAf_ATTR_IS_REQUIRED = 0x0080,
+ MOOSE_MIf_ATTR_IS_LAZY = 0x0020,
+ MOOSE_MIf_ATTR_IS_WEAK_REF = 0x0040,
+ MOOSE_MIf_ATTR_IS_REQUIRED = 0x0080,
- MAf_ATTR_SHOULD_COERCE = 0x0100,
+ MOOSE_MIf_ATTR_SHOULD_COERCE = 0x0100,
- MAf_ATTR_SHOULD_AUTO_DEREF
- = 0x0200,
- MAf_TC_IS_ARRAYREF = 0x0400,
- MAf_TC_IS_HASHREF = 0x0800,
+ MOOSE_MIf_ATTR_SHOULD_AUTO_DEREF
+ = 0x0200,
+ MOOSE_MIf_TC_IS_ARRAYREF = 0x0400,
+ MOOSE_MIf_TC_IS_HASHREF = 0x0800,
- MAf_OTHER1 = 0x1000,
- MAf_OTHER2 = 0x2000,
- MAf_OTHER3 = 0x4000,
- MAf_OTHER4 = 0x8000,
+ MOOSE_MIf_OTHER1 = 0x1000,
+ MOOSE_MIf_OTHER2 = 0x2000,
+ MOOSE_MIf_OTHER3 = 0x4000,
+ MOOSE_MIf_OTHER4 = 0x8000,
- MAf_MASK = 0xFFFF /* not used */
+ MOOSE_MIf_MOOSE_MISK = 0xFFFF /* not used */
};
STRLEN klen;
const char* const kpv = SvPV_const(key, klen);
- CV* const xsub = mop_install_accessor(aTHX_ NULL /* anonymous */, kpv, klen, accessor_impl, instance_vtbl);
- MAGIC* const mg = mop_accessor_get_mg(aTHX_ xsub);
- AV* const meta = MOP_mg_meta(mg);
- U16 flags = 0;
+ CV* const xsub = mop_install_accessor(aTHX_ NULL /* anonymous */, kpv, klen, accessor_impl, instance_vtbl);
+ dMOP_mg(xsub);
+
+ AV* const mi = MOP_mg_mi(mg);
+ U16 flags = 0;
assert(instance_vtbl);
assert(sv_isobject(metaclass));
assert(sv_isobject(instance));
assert(sv_isobject(attr));
- /* setup meta information */
+ /* setup mi information */
- av_extend(meta, MA_size - 1);
+ av_extend(mi, MOOSE_MI_last - 1);
- av_store(meta, MA_ACCESSOR, sv_rvweaken(newSVsv(accessor)));
- av_store(meta, MA_CLASS, sv_rvweaken(newSVsv(metaclass)));
- av_store(meta, MA_INSTANCE, sv_rvweaken(newSVsv(instance)));
- av_store(meta, MA_ATTRIBUTE, sv_rvweaken(newSVsv(attr)));
+ av_store(mi, MOOSE_MI_ACCESSOR, sv_rvweaken(newSVsv(accessor)));
+ av_store(mi, MOOSE_MI_CLASS, sv_rvweaken(newSVsv(metaclass)));
+ av_store(mi, MOOSE_MI_INSTANCE, sv_rvweaken(newSVsv(instance)));
+ av_store(mi, MOOSE_MI_ATTRIBUTE, sv_rvweaken(newSVsv(attr)));
/* prepare attribute status */
/* XXX: making it lazy is a good way? */
if(SvTRUEx(mop_call0_pvs(attr, "has_type_constraint"))){
SV* tc;
- flags |= MAf_ATTR_HAS_TC;
+ flags |= MOOSE_MIf_ATTR_HAS_TC;
ENTER;
SAVETMPS;
tc = mop_call0_pvs(attr, "type_constraint");
- av_store(meta, MA_TC, newSVsv(tc));
+ av_store(mi, MOOSE_MI_TC, newSVsv(tc));
if(SvTRUEx(mop_call0_pvs(attr, "should_auto_deref"))){
- flags |= MAf_ATTR_SHOULD_AUTO_DEREF;
+ flags |= MOOSE_MIf_ATTR_SHOULD_AUTO_DEREF;
if( SvTRUEx(mop_call1_pvs(tc, "is_a_type_of", newSVpvs_flags("ArrayRef", SVs_TEMP))) ){
- flags |= MAf_TC_IS_ARRAYREF;
+ flags |= MOOSE_MIf_TC_IS_ARRAYREF;
}
else if( SvTRUEx(mop_call1_pvs(tc, "is_a_type_of", newSVpvs_flags("HashRef", SVs_TEMP))) ){
- flags |= MAf_TC_IS_HASHREF;
+ flags |= MOOSE_MIf_TC_IS_HASHREF;
}
else{
moose_throw_error(accessor, tc,
}
if(SvTRUEx(mop_call0_pvs(attr, "should_coerce"))){
- flags |= MAf_ATTR_SHOULD_COERCE;
+ flags |= MOOSE_MIf_ATTR_SHOULD_COERCE;
}
FREETMPS;
}
if(SvTRUEx(mop_call0_pvs(attr, "has_default"))){
- flags |= MAf_ATTR_HAS_DEFAULT;
+ flags |= MOOSE_MIf_ATTR_HAS_DEFAULT;
}
if(SvTRUEx(mop_call0_pvs(attr, "has_builder"))){
- flags |= MAf_ATTR_HAS_BUILDER;
+ flags |= MOOSE_MIf_ATTR_HAS_BUILDER;
}
if(SvTRUEx(mop_call0_pvs(attr, "has_initializer"))){
- flags |= MAf_ATTR_HAS_INITIALIZER;
+ flags |= MOOSE_MIf_ATTR_HAS_INITIALIZER;
}
if(SvTRUEx(mop_call0_pvs(attr, "has_trigger"))){
- flags |= MAf_ATTR_HAS_TRIGGER;
+ flags |= MOOSE_MIf_ATTR_HAS_TRIGGER;
}
if(SvTRUEx(mop_call0_pvs(attr, "is_lazy"))){
- flags |= MAf_ATTR_IS_LAZY;
+ flags |= MOOSE_MIf_ATTR_IS_LAZY;
}
if(SvTRUEx(mop_call0_pvs(attr, "is_weak_ref"))){
- flags |= MAf_ATTR_IS_WEAK_REF;
+ flags |= MOOSE_MIf_ATTR_IS_WEAK_REF;
}
if(SvTRUEx(mop_call0_pvs(attr, "is_required"))){
- flags |= MAf_ATTR_IS_REQUIRED;
+ flags |= MOOSE_MIf_ATTR_IS_REQUIRED;
}
- mg->mg_private = flags;
+ MOP_mg_flags(mg) = flags;
return xsub;
}
static SV*
-moose_apply_tc(pTHX_ AV* const meta, SV* value, U16 const flags){
- SV* const tc = MA_tc(meta);
+moose_apply_tc(pTHX_ AV* const mi, SV* value, U16 const flags){
+ SV* const tc = MOOSE_mi_tc(mi);
SV* tc_code;
- if(flags & MAf_ATTR_SHOULD_COERCE){
+ if(flags & MOOSE_MIf_ATTR_SHOULD_COERCE){
value = mop_call1_pvs(tc, "coerce", value);
}
- if(!SvOK(MA_tc_code(meta))){
+ if(!SvOK(MOOSE_mi_tc_code(mi))){
tc_code = mop_call0_pvs(tc, "_compiled_type_constraint");
- av_store(meta, MA_TC_CODE, newSVsv(tc_code));
+ av_store(mi, MOOSE_MI_TC_CODE, newSVsv(tc_code));
}
else{
- tc_code = MA_tc_code(meta);
+ tc_code = MOOSE_mi_tc_code(mi);
}
/* TODO: implement build-in type constrains in XS */
PUTBACK;
if(!ok){
- moose_throw_error(MA_accessor(meta), value,
+ moose_throw_error(MOOSE_mi_accessor(mi), value,
"Attribute (%"SVf") does not pass the type constraint because: %"SVf,
- MA_key(meta),
+ MOOSE_mi_slot(mi),
mop_call1_pvs(tc, "get_message", value));
}
}
/* pushes return values, does auto-deref if needed */
static void
-moose_push_values(pTHX_ AV* const meta, SV* const value, U16 const flags){
+moose_push_values(pTHX_ AV* const mi, SV* const value, U16 const flags){
dSP;
- if(flags & MAf_ATTR_SHOULD_AUTO_DEREF && GIMME_V == G_ARRAY){
+ if(flags & MOOSE_MIf_ATTR_SHOULD_AUTO_DEREF && GIMME_V == G_ARRAY){
if(!(value && SvOK(value))){
return;
}
- if(flags & MAf_TC_IS_ARRAYREF){
+ if(flags & MOOSE_MIf_TC_IS_ARRAYREF){
AV* const av = (AV*)SvRV(value);
I32 len;
I32 i;
if(SvTYPE(av) != SVt_PVAV){
croak("Moose: panic: Not an ARRAY reference for %"SVf,
- MA_key(meta));
+ MOOSE_mi_slot(mi));
}
len = av_len(av) + 1;
PUSHs(svp ? *svp : &PL_sv_undef);
}
}
- else if(flags & MAf_TC_IS_HASHREF){
+ else if(flags & MOOSE_MIf_TC_IS_HASHREF){
HV* const hv = (HV*)SvRV(value);
HE* he;
if(SvTYPE(hv) != SVt_PVHV){
croak("Moose: panic: Not a HASH reference for %"SVf,
- MA_key(meta));
+ MOOSE_mi_slot(mi));
}
hv_iterinit(hv);
static void
moose_attr_get(pTHX_ SV* const self, MAGIC* const mg){
- AV* const meta = MOP_mg_meta(mg);
- U16 const flags = mg->mg_private;
- SV* const key = MA_key(meta);
+ AV* const mi = MOP_mg_mi(mg);
+ U16 const flags = MOP_mg_flags(mg);
/* check_lazy */
- if( flags & MAf_ATTR_IS_LAZY && !(MOP_mg_vtbl(mg)->has_slot(aTHX_ self, key)) ){
+ if( flags & MOOSE_MIf_ATTR_IS_LAZY && !MOP_mg_has_slot(mg, self) ){
SV* value = NULL;
- SV* const attr = MA_attribute(meta);
+ SV* const attr = MOOSE_mi_attribute(mi);
/* get default value by $attr->default or $attr->builder */
- if(flags & MAf_ATTR_HAS_DEFAULT){
+ if(flags & MOOSE_MIf_ATTR_HAS_DEFAULT){
value = mop_call1_pvs(attr, "default", self);
}
- else if(flags & MAf_ATTR_HAS_BUILDER){
+ else if(flags & MOOSE_MIf_ATTR_HAS_BUILDER){
SV* const builder = mop_call0_pvs(attr, "builder");
SV* const method = mop_call1_pvs(self, "can", builder);
if(SvOK(method)){
value = mop_call0(aTHX_ self, method);
}
else{
- moose_throw_error(MA_accessor(meta), NULL,
+ moose_throw_error(MOOSE_mi_accessor(mi), NULL,
"%s does not support builder method '%"SVf"' for attribute '%"SVf"'",
HvNAME_get(SvSTASH(SvRV(self))), /* ref($self) */
builder,
- key);
+ MOOSE_mi_slot(mi));
}
}
}
/* apply coerce and type constraint */
- if(flags & MAf_ATTR_HAS_TC){
- value = moose_apply_tc(aTHX_ meta, value, flags);
+ if(flags & MOOSE_MIf_ATTR_HAS_TC){
+ value = moose_apply_tc(aTHX_ mi, value, flags);
}
/* store value to slot, or invoke initializer */
- if(!(flags & MAf_ATTR_HAS_INITIALIZER)){
- (void)MOP_mg_vtbl(mg)->set_slot(aTHX_ self, key, value);
+ if(!(flags & MOOSE_MIf_ATTR_HAS_INITIALIZER)){
+ (void)MOP_mg_set_slot(mg, self, value);
}
else{
/* $attr->set_initial_value($self, $value) */
PUSHMARK(SP);
EXTEND(SP, 3);
- PUSHs(MA_attribute(meta));
+ PUSHs(MOOSE_mi_attribute(mi));
PUSHs(self);
PUSHs(value);
PUTBACK;
}
}
- moose_push_values(aTHX_ meta, MOP_mg_vtbl(mg)->get_slot(aTHX_ self, key), flags);
+ moose_push_values(aTHX_ mi, MOP_mg_get_slot(mg, self), flags);
}
static void
moose_attr_set(pTHX_ SV* const self, MAGIC* const mg, SV* value){
- AV* const meta = MOP_mg_meta(mg);
- U16 const flags = mg->mg_private;
- SV* const key = MA_key(meta);
- SV* old_value = NULL;
+ AV* const mi = MOP_mg_mi(mg);
+ U16 const flags = MOP_mg_flags(mg);
+ SV* old_value = NULL;
/*
- if(flags & MAf_ATTR_IS_REQUIRED){
+ if(flags & MOOSE_MIf_ATTR_IS_REQUIRED){
// XXX: What I should do?
}
*/
- if(flags & MAf_ATTR_HAS_TC){
- value = moose_apply_tc(aTHX_ meta, value, flags);
+ if(flags & MOOSE_MIf_ATTR_HAS_TC){
+ value = moose_apply_tc(aTHX_ mi, value, flags);
}
/* get old value for trigger */
- if(flags & MAf_ATTR_HAS_TRIGGER){
- old_value = MOP_mg_vtbl(mg)->get_slot(aTHX_ self, key);
+ if(flags & MOOSE_MIf_ATTR_HAS_TRIGGER){
+ old_value = MOP_mg_get_slot(mg, self);
if(old_value){
/* XXX: need deep copy for auto-deref? */
old_value = newSVsv(old_value);
}
}
- MOP_mg_vtbl(mg)->set_slot(aTHX_ self, key, value);
+ MOP_mg_set_slot(mg, self, value);
- if(flags & MAf_ATTR_IS_WEAK_REF){
- MOP_mg_vtbl(mg)->weaken_slot(aTHX_ self, key);
+ if(flags & MOOSE_MIf_ATTR_IS_WEAK_REF){
+ MOP_mg_weaken_slot(mg, self);
}
- if(flags & MAf_ATTR_HAS_TRIGGER){
- SV* const trigger = mop_call0_pvs(MA_attribute(meta), "trigger");
+ if(flags & MOOSE_MIf_ATTR_HAS_TRIGGER){
+ SV* const trigger = mop_call0_pvs(MOOSE_mi_attribute(mi), "trigger");
dSP;
PUSHMARK(SP);
if(old_value){
PUTBACK;
- moose_push_values(aTHX_ meta, old_value, flags);
+ moose_push_values(aTHX_ mi, old_value, flags);
SPAGAIN;
}
moose_attr_set(aTHX_ self, mg, ST(1));
}
else{
- moose_throw_error(MA_accessor(MOP_mg_meta(mg)), NULL,
+ moose_throw_error(MOOSE_mg_accessor(mg), NULL,
"expected exactly one or two argument");
}
}
for(i = 0; i < items; i++){
av_push(args, newSVsv(ST(i)));
}
- moose_throw_error(MA_accessor(MOP_mg_meta(mg)), newRV_noinc((SV*)args),
+ moose_throw_error(MOOSE_mg_accessor(mg), newRV_noinc((SV*)args),
"Cannot assign a value to a read-only accessor '%s'", GvNAME(CvGV(cv)));
}
dMOP_METHOD_COMMON; /* self, mg */
if (items != 2) {
- moose_throw_error(MA_accessor(MOP_mg_meta(mg)), NULL,
+ moose_throw_error(MOOSE_mg_accessor(mg), NULL,
"expected exactly two arguments");
}