This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Mark scripts, modules and tests as linguist-language=Perl
[perl5.git] / builtin.c
CommitLineData
6a2e756f
PE
1/* builtin.c
2 *
3 * Copyright (C) 2021 by Paul Evans and others
4 *
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
7 *
8 */
9
10/* This file contains the code that implements functions in perl's "builtin::"
11 * namespace
12 */
13
14#include "EXTERN.h"
15#include "perl.h"
16
17#include "XSUB.h"
18
852c1a84
PE
19struct BuiltinFuncDescriptor {
20 const char *name;
21 XSUBADDR_t xsub;
22 OP *(*checker)(pTHX_ OP *, GV *, SV *);
23 IV ckval;
24};
25
6a2e756f
PE
26XS(XS_builtin_true);
27XS(XS_builtin_true)
28{
29 dXSARGS;
30 if(items)
31 croak_xs_usage(cv, "");
32 XSRETURN_YES;
33}
34
35XS(XS_builtin_false);
36XS(XS_builtin_false)
37{
38 dXSARGS;
39 if(items)
40 croak_xs_usage(cv, "");
41 XSRETURN_NO;
42}
43
852c1a84
PE
44enum {
45 BUILTIN_CONST_FALSE,
46 BUILTIN_CONST_TRUE,
47};
48
49static OP *ck_builtin_const(pTHX_ OP *entersubop, GV *namegv, SV *ckobj)
50{
51 const struct BuiltinFuncDescriptor *builtin = NUM2PTR(const struct BuiltinFuncDescriptor *, SvUV(ckobj));
52
53 SV *prototype = newSVpvs("");
54 SAVEFREESV(prototype);
55
56 assert(entersubop->op_type == OP_ENTERSUB);
57
58 entersubop = ck_entersub_args_proto(entersubop, namegv, prototype);
59
60 SV *constval;
61 switch(builtin->ckval) {
62 case BUILTIN_CONST_FALSE: constval = &PL_sv_no; break;
63 case BUILTIN_CONST_TRUE: constval = &PL_sv_yes; break;
64 default:
65 DIE(aTHX_ "panic: unrecognised builtin_const value %" IVdf, builtin->ckval);
66 break;
67 }
68
69 op_free(entersubop);
70
71 return newSVOP(OP_CONST, 0, constval);
72}
73
74enum {
75 BUILTIN_FUNC1_ISBOOL = 1,
76};
77
78XS(XS_builtin_func1);
79XS(XS_builtin_func1)
6a2e756f
PE
80{
81 dXSARGS;
852c1a84
PE
82 dXSI32;
83
6a2e756f 84 if(items != 1)
852c1a84
PE
85 croak_xs_usage(cv, "arg");
86
87 switch(ix) {
88 case BUILTIN_FUNC1_ISBOOL:
89 Perl_pp_isbool(aTHX);
90 break;
6a2e756f 91
852c1a84
PE
92 default:
93 Perl_die(aTHX_ "panic: unhandled ix value %d for xs_builtin_func1()", ix);
94 }
95
96 XSRETURN(1);
97}
98
99static OP *ck_builtin_func1(pTHX_ OP *entersubop, GV *namegv, SV *ckobj)
100{
101 const struct BuiltinFuncDescriptor *builtin = NUM2PTR(const struct BuiltinFuncDescriptor *, SvUV(ckobj));
102
103 SV *prototype = newSVpvs("$");
104 SAVEFREESV(prototype);
105
106 assert(entersubop->op_type == OP_ENTERSUB);
107
108 entersubop = ck_entersub_args_proto(entersubop, namegv, prototype);
109
110 OP *parent = entersubop, *pushop, *argop;
111
112 pushop = cUNOPx(entersubop)->op_first;
113 if (!OpHAS_SIBLING(pushop)) {
114 pushop = cUNOPx(pushop)->op_first;
115 }
116
117 argop = OpSIBLING(pushop);
118
119 if (!argop || !OpHAS_SIBLING(argop) || OpHAS_SIBLING(OpSIBLING(argop)))
120 return entersubop;
121
122 (void)op_sibling_splice(parent, pushop, 1, NULL);
123
1c57e396 124 U8 wantflags = entersubop->op_flags & OPf_WANT;
852c1a84
PE
125
126 op_free(entersubop);
127
128 OPCODE opcode;
129 switch(builtin->ckval) {
130 case BUILTIN_FUNC1_ISBOOL: opcode = OP_ISBOOL; break;
131 default:
132 DIE(aTHX_ "panic: unhandled ckval value %" IVdf " for ck_builtin_func1()", builtin->ckval);
133 }
134
1c57e396 135 return newUNOP(opcode, wantflags, argop);
6a2e756f
PE
136}
137
a64a1b91
DIM
138static const char builtin_not_recognised[] = "'%" SVf "' is not recognised as a builtin function";
139
852c1a84
PE
140static const struct BuiltinFuncDescriptor builtins[] = {
141 /* constants */
142 { "builtin::true", &XS_builtin_true, &ck_builtin_const, BUILTIN_CONST_TRUE },
143 { "builtin::false", &XS_builtin_false, &ck_builtin_const, BUILTIN_CONST_FALSE },
144
145 /* unary functions */
146 { "builtin::isbool", &XS_builtin_func1, &ck_builtin_func1, BUILTIN_FUNC1_ISBOOL },
147 { 0 }
148};
149
6a2e756f
PE
150XS(XS_builtin_import);
151XS(XS_builtin_import)
152{
153 dXSARGS;
154
155 if(!PL_compcv)
156 Perl_croak(aTHX_
157 "builtin::import can only be called at compiletime");
158
159 /* We need to have PL_comppad / PL_curpad set correctly for lexical importing */
160 ENTER;
161 SAVESPTR(PL_comppad_name); PL_comppad_name = PadlistNAMES(CvPADLIST(PL_compcv));
162 SAVESPTR(PL_comppad); PL_comppad = PadlistARRAY(CvPADLIST(PL_compcv))[1];
163 SAVESPTR(PL_curpad); PL_curpad = PadARRAY(PL_comppad);
164
165 for(int i = 1; i < items; i++) {
166 SV *sym = ST(i);
a64a1b91
DIM
167 if(strEQ(SvPV_nolen(sym), "import"))
168 Perl_croak(aTHX_ builtin_not_recognised, sym);
6a2e756f
PE
169
170 SV *ampname = sv_2mortal(Perl_newSVpvf(aTHX_ "&%" SVf, SVfARG(sym)));
171 SV *fqname = sv_2mortal(Perl_newSVpvf(aTHX_ "builtin::%" SVf, SVfARG(sym)));
172
173 CV *cv = get_cv(SvPV_nolen(fqname), SvUTF8(fqname) ? SVf_UTF8 : 0);
a64a1b91
DIM
174 if(!cv)
175 Perl_croak(aTHX_ builtin_not_recognised, sym);
6a2e756f
PE
176
177 PADOFFSET off = pad_add_name_sv(ampname, padadd_STATE, 0, 0);
178 SvREFCNT_dec(PL_curpad[off]);
179 PL_curpad[off] = SvREFCNT_inc(cv);
6a2e756f
PE
180 }
181
182 intro_my();
183
184 LEAVE;
185}
186
187void
188Perl_boot_core_builtin(pTHX)
189{
852c1a84
PE
190 I32 i;
191 for(i = 0; builtins[i].name; i++) {
192 const struct BuiltinFuncDescriptor *builtin = &builtins[i];
193
194 const char *proto = NULL;
195 if(builtin->checker == &ck_builtin_const)
196 proto = "";
197 else if(builtin->checker == &ck_builtin_func1)
198 proto = "$";
199
200 CV *cv = newXS_flags(builtin->name, builtin->xsub, __FILE__, proto, 0);
201 XSANY.any_i32 = builtin->ckval;
202
203 if(builtin->checker) {
204 cv_set_call_checker_flags(cv, builtin->checker, newSVuv(PTR2UV(builtin)), 0);
205 }
206 }
6a2e756f
PE
207
208 newXS_flags("builtin::import", &XS_builtin_import, __FILE__, NULL, 0);
209}
210
211/*
212 * ex: set ts=8 sts=4 sw=4 et:
213 */