This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
More PAD APIs
authorFather Chrysostomos <sprout@cpan.org>
Fri, 17 Aug 2012 21:21:37 +0000 (14:21 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Tue, 21 Aug 2012 23:51:16 +0000 (16:51 -0700)
If we are making padlists their own type, and no longer AVs, it makes
sense to add APIs for pads, too, so that CPAN code that needs to
change now will only have to change once if we ever stop pads them-
selves from being AVs.

There is no reason pad names have to be SVs, so I am adding sep-
arate APIs for pad names, too.  The AV containing pad names is
now officially a PADNAMELIST, which is accessed, not via
*PADLIST_ARRAY(padlist), but via PADLIST_NAMES(padlist).

Future optimisations may even merge the padlist with its name list so
I have also added macros to access the parts of the name list directly
from the padlist.

ext/XS-APItest/APItest.xs
pad.h
perl.h
sv.h

index 0519920..fb42935 100644 (file)
@@ -3287,16 +3287,16 @@ fetch_pad_names( cv )
 CV* cv
  PREINIT:
   I32 i;
 CV* cv
  PREINIT:
   I32 i;
-  AV *pad_namelist;
+  PADNAMELIST *pad_namelist;
   AV *retav = newAV();
  CODE:
   AV *retav = newAV();
  CODE:
-  pad_namelist = *PADLIST_ARRAY(CvPADLIST(cv));
+  pad_namelist = PADLIST_NAMES(CvPADLIST(cv));
 
 
-  for ( i = av_len(pad_namelist); i >= 0; i-- ) {
-    SV** name_ptr = av_fetch(pad_namelist, i, 0);
+  for ( i = PADNAMELIST_MAX(pad_namelist); i >= 0; i-- ) {
+    PADNAME* name = PADNAMELIST_ARRAY(pad_namelist)[i];
 
 
-    if (name_ptr && SvPOKp(*name_ptr)) {
-        av_push(retav, newSVsv(*name_ptr));
+    if (SvPOKp(name)) {
+        av_push(retav, newSVpadname(name));
     }
   }
   RETVAL = newRV_noinc((SV*)retav);
     }
   }
   RETVAL = newRV_noinc((SV*)retav);
diff --git a/pad.h b/pad.h
index 314db98..05bbc62 100644 (file)
--- a/pad.h
+++ b/pad.h
@@ -175,7 +175,55 @@ Clear the pointed to pad value on scope exit. (i.e. the runtime action of 'my')
 save PL_comppad and PL_curpad
 
 
 save PL_comppad and PL_curpad
 
 
+=for apidoc Amx|PAD **|PADLIST_ARRAY|PADLIST padlist
+The C array of a padlist, containing the pads.  Only subscript it with
+numbers >= 1, as the 0th entry is not guaranteed to remain usable.
 
 
+=for apidoc Amx|SSize_t|PADLIST_MAX|PADLIST padlist
+The index of the last pad in the padlist.
+
+=for apidoc Amx|PADNAMELIST *|PADLIST_NAMES|PADLIST padlist
+The names associated with pad entries.
+
+=for apidoc Amx|PADNAME **|PADLIST_NAMESARRAY|PADLIST padlist
+The C array of pad names.
+
+=for apidoc Amx|SSize_t|PADLIST_NAMESMAX|PADLIST padlist
+The index of the last pad name.
+
+=for apidoc Amx|U32|PADLIST_REFCNT|PADLIST padlist
+The reference count of the padlist.  Currently this is always 1.
+
+=for apidoc Amx|PADNAME **|PADNAMELIST_ARRAY|PADNAMELIST pnl
+The C array of pad names.
+
+=for apidoc Amx|SSize_t|PADNAMELIST_MAX|PADNAMELIST pnl
+The index of the last pad name.
+
+=for apidoc Amx|SV **|PAD_ARRAY|PAD pad
+The C array of pad entries.
+
+=for apidoc Amx|SSize_t|PAD_MAX|PAD pad
+The index of the last pad entry.
+
+=for apidoc Amx|char *|PADNAME_PV|PADNAME pn   
+The name stored in the pad name struct.
+
+=for apidoc Amx|STRLEN|PADNAME_LEN|PADNAME pn  
+The length of the name.
+
+=for apidoc Amx|bool|PADNAME_UTF8|PADNAME pn
+Whether PADNAME_PV is in UTF8.
+
+=for apidoc m|bool|PADNAME_isOUR|PADNAME pn
+Whether this is an "our" variable.
+
+=for apidoc m|HV *|PADNAME_OURSTASH
+The stash in which this "our" variable was declared.
+
+=for apidoc m|HV *|PADNAME_TYPE|PADNAME pn
+The stash associated with a typed lexical.  This returns the %Foo:: hash
+for C<my Foo $bar>.
 
 
 =for apidoc m|SV *|PAD_SETSV   |PADOFFSET po|SV* sv
 
 
 =for apidoc m|SV *|PAD_SETSV   |PADOFFSET po|SV* sv
@@ -220,8 +268,25 @@ Restore the old pad saved into the local variable opad by PAD_SAVE_LOCAL()
 
 #define PADLIST_ARRAY(pl)      (pl)->xpadl_alloc
 #define PADLIST_MAX(pl)                (pl)->xpadl_max
 
 #define PADLIST_ARRAY(pl)      (pl)->xpadl_alloc
 #define PADLIST_MAX(pl)                (pl)->xpadl_max
+#define PADLIST_NAMES(pl)      (*PADLIST_ARRAY(pl))
+#define PADLIST_NAMESARRAY(pl) PADNAMELIST_ARRAY(PADLIST_NAMES(pl))
+#define PADLIST_NAMESMAX(pl)   PADNAMELIST_MAX(PADLIST_NAMES(pl))
 #define PADLIST_REFCNT(pl)     1       /* reserved for future use */
 
 #define PADLIST_REFCNT(pl)     1       /* reserved for future use */
 
+#define PADNAMELIST_ARRAY(pnl) AvARRAY(pnl)
+#define PADNAMELIST_MAX(pnl)   AvFILLp(pnl)
+
+#define PAD_ARRAY(pad)         AvARRAY(pad)
+#define PAD_MAX(pad)           AvFILLp(pad)
+
+#define PADNAME_PV(pn)         SvPV_nolen(pn)
+#define PADNAME_LEN(pn)                SvCUR(pn)
+#define PADNAME_UTF8(pn)       !!SvUTF8(pn)
+#define PADNAME_isOUR(pn)      !!SvPAD_OUR(pn)
+#define PADNAME_OURSTASH       SvOURSTASH(pn)
+#define PADNAME_TYPE(pn)       (SvPAD_TYPED(pn) ? SvSTASH(pn) : NULL)
+
+
 #ifdef DEBUGGING
 #  define PAD_SV(po)      pad_sv(po)
 #  define PAD_SETSV(po,sv) pad_setsv(po,sv)
 #ifdef DEBUGGING
 #  define PAD_SV(po)      pad_sv(po)
 #  define PAD_SETSV(po,sv) pad_setsv(po,sv)
@@ -316,6 +381,7 @@ ling pad (lvalue) to C<gen>.  Note that C<SvUV_set> is hijacked for this purpose
 
 */
 
 
 */
 
+#define PAD_COMPNAME(po)       PAD_COMPNAME_SV(po)
 #define PAD_COMPNAME_SV(po) (*av_fetch(PL_comppad_name, (po), FALSE))
 #define PAD_COMPNAME_FLAGS(po) SvFLAGS(PAD_COMPNAME_SV(po))
 #define PAD_COMPNAME_FLAGS_isOUR(po) SvPAD_OUR(PAD_COMPNAME_SV(po))
 #define PAD_COMPNAME_SV(po) (*av_fetch(PL_comppad_name, (po), FALSE))
 #define PAD_COMPNAME_FLAGS(po) SvFLAGS(PAD_COMPNAME_SV(po))
 #define PAD_COMPNAME_FLAGS_isOUR(po) SvPAD_OUR(PAD_COMPNAME_SV(po))
diff --git a/perl.h b/perl.h
index 1154c40..36eec0d 100644 (file)
--- a/perl.h
+++ b/perl.h
@@ -2442,10 +2442,12 @@ typedef struct ptr_tbl_ent PTR_TBL_ENT_t;
 typedef struct ptr_tbl PTR_TBL_t;
 typedef struct clone_params CLONE_PARAMS;
 
 typedef struct ptr_tbl PTR_TBL_t;
 typedef struct clone_params CLONE_PARAMS;
 
-/* a pad is currently just an AV; but that might change,
+/* a pad or name pad is currently just an AV; but that might change,
  * so hide the type.  */
 typedef struct padlist PADLIST;
 typedef AV PAD;
  * so hide the type.  */
 typedef struct padlist PADLIST;
 typedef AV PAD;
+typedef AV PADNAMELIST;
+typedef SV PADNAME;
 
 #include "handy.h"
 
 
 #include "handy.h"
 
diff --git a/sv.h b/sv.h
index 7ec1c05..38b2f20 100644 (file)
--- a/sv.h
+++ b/sv.h
@@ -1998,6 +1998,18 @@ C<SvUTF8_on> on the new SV.  Implemented as a wrapper around C<newSVpvn_flags>.
 #define newSVpvn_utf8(s, len, u) newSVpvn_flags((s), (len), (u) ? SVf_UTF8 : 0)
 
 /*
 #define newSVpvn_utf8(s, len, u) newSVpvn_flags((s), (len), (u) ? SVf_UTF8 : 0)
 
 /*
+=for apidoc Amx|SV*|newSVpadname|PADNAME *pn
+
+Creates a new SV containing the pad name.  This is currently identical
+to C<newSVsv>, but pad names may cease being SVs at some point, so
+C<newSVpadname> is preferable.
+
+=cut
+*/
+
+#define newSVpadname(pn) newSVsv(pn)
+
+/*
 =for apidoc Am|void|SvOOK_offset|NN SV*sv|STRLEN len
 
 Reads into I<len> the offset from SvPVX back to the true start of the
 =for apidoc Am|void|SvOOK_offset|NN SV*sv|STRLEN len
 
 Reads into I<len> the offset from SvPVX back to the true start of the