Object-Pad

 view release on metacpan or  search on metacpan

lib/Object/Pad.xs  view on Meta::CPAN

    dump_fieldmeta(aTHX_ ctx, fieldmeta);
  }

  for(i = 0; i < av_count(classmeta->direct_methods); i++) {
    MethodMeta *methodmeta = MUST_METHODMETA(AvARRAY(classmeta->direct_methods)[i]);

    dump_methodmeta(aTHX_ ctx, methodmeta);
  }

  HV *parammap;
  if((parammap = classmeta->parammap)) {
    hv_iterinit(parammap);

    HE *iter;
    while((iter = hv_iternext(parammap))) {
      ParamMeta *parammeta = MUST_PARAMMETA(HeVAL(iter));

      dump_parammeta(aTHX_ ctx, parammeta);
    }
  }

  switch(classmeta->type) {
    case METATYPE_CLASS:
      for(i = 0; i < av_count(classmeta->cls.direct_roles); i++) {
        RoleEmbedding *embedding = MUST_ROLEEMBEDDING(AvARRAY(classmeta->cls.direct_roles)[i]);

        dump_roleembedding(aTHX_ ctx, embedding);
      }
      break;

    case METATYPE_ROLE:
      /* No need to dump the values of role.applied_classes because any class
       * they're applied to will have done that already */
      break;
  }
}

static int dumppackage_class(pTHX_ DMDContext *ctx, const SV *sv)
{
  int ret = 0;

  ClassMeta *meta = MUST_CLASSMETA(SvUV((SV *)sv));

  dump_classmeta(aTHX_ ctx, meta);

  ret += DMD_ANNOTATE_SV(sv, (SV *)meta, "the Object::Pad class");

  return ret;
}
#endif

/*********************
 * Custom FieldHooks *
 *********************/

struct CustomFieldHookData
{
  SV *apply_cb;
};

static bool fieldhook_custom_apply(pTHX_ FieldMeta *fieldmeta, SV *value, SV **hookdata_ptr, void *_funcdata)
{
  struct CustomFieldHookData *funcdata = _funcdata;

  SV *cb;
  if((cb = funcdata->apply_cb)) {
    dSP;
    ENTER;
    SAVETMPS;

    SV *fieldmetasv = sv_newmortal();
    sv_setref_uv(fieldmetasv, "Object::Pad::MOP::Field", PTR2UV(fieldmeta));

    PUSHMARK(SP);
    EXTEND(SP, 2);
    PUSHs(fieldmetasv);
    PUSHs(value);
    PUTBACK;

    call_sv(cb, G_SCALAR);

    SPAGAIN;
    SV *ret = POPs;
    *hookdata_ptr = SvREFCNT_inc(ret);

    FREETMPS;
    LEAVE;
  }

  return TRUE;
}

/* internal function shared by various *.c files */
void ObjectPad__need_PLparser(pTHX)
{
  if(!PL_parser) {
    /* We need to generate just enough of a PL_parser to keep newSTATEOP()
     * happy, otherwise it will SIGSEGV (RT133258)
     */
    SAVEVPTR(PL_parser);
    Newxz(PL_parser, 1, yy_parser);
    SAVEFREEPV(PL_parser);

    PL_parser->copline = NOLINE;
#if HAVE_PERL_VERSION(5, 20, 0)
    PL_parser->preambling = NOLINE;
#endif
  }
}

/* used by XSUB deconstruct_object */
#define deconstruct_object_class(fieldstore, classmeta, offset)  S_deconstruct_object_class(aTHX_ fieldstore, classmeta, offset)
static U32 S_deconstruct_object_class(pTHX_ SV *fieldstore, ClassMeta *classmeta, FIELDOFFSET offset)
{
  dSP;
  U32 retcount = 0;
  AV *fields = classmeta->fields;
  U32 nfields = av_count(fields);

  EXTEND(SP, nfields * 2);

  SV **fieldsvs = fieldstore_fields(fieldstore);

  FIELDOFFSET i;
  for(i = 0; i < nfields; i++) {
    FieldMeta *fieldmeta = MUST_FIELDMETA(AvARRAY(fields)[i]);

lib/Object/Pad.xs  view on Meta::CPAN


/* Handy functions for MOP wrapper methods */
#define MUST_CLASSMETA_FROM_RV(self)  S_must_classmeta_from_rv(aTHX_ self)
static ClassMeta *S_must_classmeta_from_rv(pTHX_ SV *self)
{
  if(!(SvROK(self) && sv_derived_from(self, "Object::Pad::MOP::Class")))
    croak("Expected an Object::Pad::MOP::Class instance");

  return MUST_CLASSMETA(NUM2PTR(ClassMeta *, SvUV(SvRV(self))));
}

#define MUST_FIELDMETA_FROM_RV(self)  S_must_fieldmeta_from_rv(aTHX_ self)
static FieldMeta *S_must_fieldmeta_from_rv(pTHX_ SV *self)
{
  if(!(SvROK(self) && sv_derived_from(self, "Object::Pad::MOP::Field")))
    croak("Expected an Object::Pad::MOP::Field instance");

  return MUST_FIELDMETA(NUM2PTR(FieldMeta *, SvUV(SvRV(self))));
}

#define MUST_METHODMETA_FROM_RV(self)  S_must_methodmeta_from_rv(aTHX_ self)
static MethodMeta *S_must_methodmeta_from_rv(pTHX_ SV *self)
{
  if(!(SvROK(self) && sv_derived_from(self, "Object::Pad::MOP::Method")))
    croak("Expected an Object::Pad::MOP::Method instance");

  return MUST_METHODMETA(NUM2PTR(MethodMeta *, SvUV(SvRV(self))));
}

MODULE = Object::Pad    PACKAGE = Object::Pad::MOP::Class

INCLUDE: mop-class.xsi

MODULE = Object::Pad    PACKAGE = Object::Pad::MOP::Method

INCLUDE: mop-method.xsi

MODULE = Object::Pad    PACKAGE = Object::Pad::MOP::Field

INCLUDE: mop-field.xsi

MODULE = Object::Pad    PACKAGE = Object::Pad::MOP::FieldAttr

void
register(class, name, ...)
  SV *class
  SV *name
  CODE:
  {
    PERL_UNUSED_VAR(class);
    dKWARG(2);

    {
      if(!cophh_exists_pvs(CopHINTHASH_get(PL_curcop), "Object::Pad/experimental(custom_field_attr)", 0))
        Perl_ck_warner(aTHX_ packWARN(WARN_EXPERIMENTAL),
          "Object::Pad::MOP::FieldAttr is experimental and may be changed or removed without notice");
    }

    struct FieldHookFuncs funcs = {};

    struct CustomFieldHookData funcdata = {};

    funcs.ver = OBJECTPAD_ABIVERSION;

    funcs.apply = &fieldhook_custom_apply;

    static const char *args[] = {
      "permit_hintkey",
      "apply",
      "no_value",
      "must_value",
      NULL,
    };
    while(KWARG_NEXT(args)) {
      switch(kwarg) {
        case 0: /* permit_hintkey */
          funcs.permit_hintkey = SvPV_nolen(kwval);
          break;

        case 1: /* apply */
          funcdata.apply_cb = kwval;
          break;

        case 2: /* no_value */
          if(SvTRUE(kwval))
            funcs.flags |= OBJECTPAD_FLAG_ATTR_NO_VALUE;
          break;

        case 3: /* must_value */
          if(SvTRUE(kwval))
            funcs.flags |= OBJECTPAD_FLAG_ATTR_MUST_VALUE;
          break;
      }
    }

    if((funcs.flags & OBJECTPAD_FLAG_ATTR_NO_VALUE) &&
       (funcs.flags & OBJECTPAD_FLAG_ATTR_MUST_VALUE))
       croak("Cannot register a FieldAttr with both 'no_value' and 'must_value'");

    struct FieldHookFuncs *_funcs;
    Newxz(_funcs, 1, struct FieldHookFuncs);
    Copy(&funcs, _funcs, 1, struct FieldHookFuncs);
    if(_funcs->permit_hintkey)
      _funcs->permit_hintkey = savepv(_funcs->permit_hintkey);

    struct CustomFieldHookData *_funcdata;
    Newxz(_funcdata, 1, struct CustomFieldHookData);
    Copy(&funcdata, _funcdata, 1, struct CustomFieldHookData);
    if(_funcdata->apply_cb)
      _funcdata->apply_cb = newSVsv(_funcdata->apply_cb);

    register_field_attribute(savepv(SvPV_nolen(name)), _funcs, _funcdata);
  }

MODULE = Object::Pad    PACKAGE = Object::Pad::MetaFunctions

SV *
metaclass(SV *obj)
  CODE:
  {
    if(!SvROK(obj) || !SvOBJECT(SvRV(obj)))
      croak("Expected an object reference to metaclass");

    HV *stash = SvSTASH(SvRV(obj));

    GV **gvp = (GV **)hv_fetchs(stash, "META", 0);
    if(!gvp)
      croak("Unable to find ClassMeta for %" HEKf, HEKfARG(HvNAME_HEK(stash)));

    RETVAL = newSVsv(GvSV(*gvp));
  }
  OUTPUT:
    RETVAL

void
deconstruct_object(SV *obj)
  PPCODE:
  {
    if(!SvROK(obj) || !SvOBJECT(SvRV(obj)))
      croak("Expected an object reference to deconstruct_object");

    ClassMeta *classmeta = mop_get_class_for_stash(SvSTASH(SvRV(obj)));

    SV *fieldstore = get_obj_fieldstore(obj, classmeta->repr, true);

    U32 retcount = 0;

    PUSHs(sv_mortalcopy(classmeta->name));
    retcount++;

    PUTBACK;

    while(classmeta) {
      retcount += deconstruct_object_class(fieldstore, classmeta, 0);

      AV *roles = classmeta->cls.direct_roles;
      U32 nroles = av_count(roles);
      for(U32 i = 0; i < nroles; i++) {
        RoleEmbedding *embedding = MUST_ROLEEMBEDDING(AvARRAY(roles)[i]);

        retcount += deconstruct_object_class(fieldstore, embedding->rolemeta, embedding->offset);
      }

      classmeta = classmeta->cls.supermeta;
    }

    SPAGAIN;
    XSRETURN(retcount);
  }

SV *
ref_field(SV *fieldname, SV *obj)



( run in 1.770 second using v1.01-cache-2.11-cpan-39bf76dae61 )