summaryrefslogtreecommitdiff
path: root/builtin.c
diff options
context:
space:
mode:
authorPaul "LeoNerd" Evans <leonerd@leonerd.org.uk>2022-07-08 22:21:12 +0100
committerPaul Evans <leonerd@leonerd.org.uk>2022-07-15 20:20:44 +0100
commitf846dd1207e4a33a3807f5f56c2bdcc6b66fe090 (patch)
treefea5c9514e36e03bf473ef189db115cc8adc6e7c /builtin.c
parentbb0dc1a9ec42b0d693aacc1c516e78ae7a337fc1 (diff)
downloadperl-f846dd1207e4a33a3807f5f56c2bdcc6b66fe090.tar.gz
Add builtin function `export_lexically()`
As per RFC 0020
Diffstat (limited to 'builtin.c')
-rw-r--r--builtin.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/builtin.c b/builtin.c
index bb782d052c..7a47842a12 100644
--- a/builtin.c
+++ b/builtin.c
@@ -263,6 +263,79 @@ XS(XS_builtin_trim)
XSRETURN(1);
}
+XS(XS_builtin_export_lexically);
+XS(XS_builtin_export_lexically)
+{
+ dXSARGS;
+
+ warn_experimental_builtin("export_lexically", true);
+
+ if(!PL_compcv)
+ Perl_croak(aTHX_
+ "export_lexically can only be called at compile time");
+
+ if(items % 2)
+ Perl_croak(aTHX_ "Odd number of elements in export_lexically");
+
+ for(int i = 0; i < items; i += 2) {
+ SV *name = ST(i);
+ SV *ref = ST(i+1);
+
+ if(!SvROK(ref))
+ /* diag_listed_as: Expected %s reference in export_lexically */
+ Perl_croak(aTHX_ "Expected a reference in export_lexically");
+
+ char sigil = SvPVX(name)[0];
+ SV *rv = SvRV(ref);
+
+ const char *bad = NULL;
+ switch(sigil) {
+ default:
+ /* overwrites the pointer on the stack; but this is fine, the
+ * caller's value isn't modified */
+ ST(i) = name = sv_2mortal(Perl_newSVpvf(aTHX_ "&%" SVf, SVfARG(name)));
+
+ /* FALLTHROUGH */
+ case '&':
+ if(SvTYPE(rv) != SVt_PVCV)
+ bad = "a CODE";
+ break;
+
+ case '$':
+ /* Permit any of SVt_NULL to SVt_PVMG. Technically this also
+ * includes SVt_INVLIST but it isn't thought possible for pureperl
+ * code to ever manage to see one of those. */
+ if(SvTYPE(rv) > SVt_PVMG)
+ bad = "a SCALAR";
+ break;
+
+ case '@':
+ if(SvTYPE(rv) != SVt_PVAV)
+ bad = "an ARRAY";
+ break;
+
+ case '%':
+ if(SvTYPE(rv) != SVt_PVHV)
+ bad = "a HASH";
+ break;
+ }
+
+ if(bad)
+ Perl_croak(aTHX_ "Expected %s reference in export_lexically", bad);
+ }
+
+ prepare_export_lexical();
+
+ for(int i = 0; i < items; i += 2) {
+ SV *name = ST(i);
+ SV *ref = ST(i+1);
+
+ export_lexical(name, SvRV(ref));
+ }
+
+ finish_export_lexical();
+}
+
XS(XS_builtin_func1_void);
XS(XS_builtin_func1_void)
{
@@ -433,6 +506,7 @@ static const struct BuiltinFuncDescriptor builtins[] = {
/* list functions */
{ "builtin::indexed", &XS_builtin_indexed, &ck_builtin_funcN, 0 },
+ { "builtin::export_lexically", &XS_builtin_export_lexically, NULL, 0 },
{ 0 }
};