File Coverage

blib/lib/Data/Sah/Compiler/perl.pm
Criterion Covered Total %
statement 164 213 77.0
branch 49 78 62.8
condition 44 71 61.9
subroutine 46 55 83.6
pod 4 47 8.5
total 307 464 66.1


line stmt bran cond sub pod time code
1              
2             use 5.010;
3 22     22   412 use strict;
  22         63  
4 22     22   99 use warnings;
  22         45  
  22         407  
5 22     22   89 use Log::ger;
  22         32  
  22         527  
6 22     22   31916  
  22         978  
  22         102  
7             use Data::Dmp qw(dmp);
8 22     22   14376 use Mo qw(build default);
  22         38469  
  22         1325  
9 22     22   151  
  22         39  
  22         127  
10             extends 'Data::Sah::Compiler::Prog';
11              
12             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
13             our $DATE = '2022-09-30'; # DATE
14             our $DIST = 'Data-Sah'; # DIST
15             our $VERSION = '0.913'; # VERSION
16              
17             our $PP;
18             our $CORE;
19             our $CORE_OR_PP;
20             our $NO_MODULES;
21              
22             # BEGIN COPIED FROM String::Indent
23             my ($indent, $str, $opts) = @_;
24             $opts //= {};
25 9949     9949   78717  
26 9949   50     36874 my $ibl = $opts->{indent_blank_lines} // 1;
27             my $fli = $opts->{first_line_indent} // $indent;
28 9949   50     29222 my $sli = $opts->{subsequent_lines_indent} // $indent;
29 9949   33     25175 #say "D:ibl=<$ibl>, fli=<$fli>, sli=<$sli>";
30 9949   33     23771  
31             my $i = 0;
32             $str =~ s/^([^\r\n]?)/$i++; !$ibl && !$1 ? "$1" : $i==1 ? "$fli$1" : "$sli$1"/egm;
33 9949         12854 $str;
34 9949 100 33     39519 }
  221410 50       233647  
  221410         645073  
35 9949         68311 # END COPIED FROM String::Indent
36              
37             my ($self, $args) = @_;
38              
39             $self->comment_style('shell');
40 4751     4751 0 205754 $self->indent_character(" " x 4);
41             $self->var_sigil('$');
42 4751         14381 $self->concat_op(".");
43 4751         30200 }
44 4751         33424  
45 4751         20541  
46             dmp($_[1]);
47             }
48 25512     25512 0 71237  
49             my ($self, %args) = @_;
50              
51 40726     40726 0 96418 #$self->expr_compiler->compiler->hook_var(
52             # sub {
53             # $_[0];
54             # }
55 5060     5060 1 36157 #);
56              
57             #$self->expr_compiler->compiler->hook_func(
58             # sub {
59             # my ($name, @args) = @_;
60             # die "Unknown function $name"
61             # unless $self->main->func_names->{$name};
62             # my $subname = "func_$name";
63             # $self->define_sub_start($subname);
64             # my $meth = "func_$name";
65             # $self->func_handlers->{$name}->$meth;
66             # $self->define_sub_end();
67             # $subname . "(" . join(", ", @args) . ")";
68             # }
69             #);
70              
71             # Data::Dumper is chosen as the default because it's core, but note here the
72             # inconveniences: 1) the incantation to use it the way we want is
73             # cumbersome. Storable is not feasible because of reason explained in
74             # comment in expr_dump(). Data::Dmp is another choice.
75             $args{dump_module} //= "Data::Dumper";
76              
77             $args{pp} //= $PP // $ENV{DATA_SAH_PP} // 0;
78             $args{core} //= $CORE // $ENV{DATA_SAH_CORE} // 0;
79             $args{core_or_pp} //= $CORE_OR_PP // $ENV{DATA_SAH_CORE_OR_PP} // 0;
80             $args{no_modules} //= $NO_MODULES // $ENV{DATA_SAH_NO_MODULES} // 0;
81 5060   100     17929  
82             $self->SUPER::compile(%args);
83 5060   66     28839 }
      50        
      100        
84 5060   66     30121  
      50        
      100        
85 5060   66     27484 my ($self, %args) = @_;
      50        
      100        
86 5060   66     28559  
      50        
      100        
87             my $cd = $self->SUPER::init_cd(%args);
88 5060         26895  
89             $self->add_runtime_no($cd, 'warnings', ["'void'"]) unless $cd->{args}{no_modules};
90              
91             $cd;
92 5060     5060 0 31235 }
93              
94 5060         26344 require Data::Cmp;
95              
96 5060 100       27779 my ($self, $cd) = @_;
97              
98 5060         28551 # check whether we can optimize and produce a shorter, faster code under
99             # certain conditions (return_type=bool, simple schemas).
100              
101             return 0 unless $cd->{args}{return_type} eq 'bool_valid';
102 5060     5060 0 29548  
103             my $nschema = $cd->{nschema};
104 5060         23553 my $dt = $cd->{args}{data_term};
105             if (Data::Cmp::cmp_data($nschema, ["int", {"req", 1}, {}]) == 0) {
106             #$cd->{result} = "!defined($dt) || (!ref($dt) && length($dt) >= 4)";
107             $self->add_runtime_module($cd, 'Scalar::Util::Numeric');
108             $cd->{result} = "Scalar::Util::Numeric::isint($dt)";
109 5060 100       16161 return 99;
110             }
111 1908         3169  
112 1908         3388 return;
113 1908 50       8417 }
114              
115 0         0  
116 0         0  
117 0         0 # quick lookup table, to avoid having to use Module::CoreList or Module::XSOrPP
118             our %known_modules = (
119             'DateTime::Duration' => {pp=>1, core=>0},
120 1908         117380 'DateTime' => {pp=>0, core=>0},
121             'DateTime::Format::Alami' => {pp=>1, core=>0},
122             'DateTime::Format::Alami::EN' => {pp=>1, core=>0},
123 20764     20764 0 44866 'DateTime::Format::Alami::ID' => {pp=>1, core=>0},
124             'DateTime::Format::Natural' => {pp=>1, core=>0},
125 90     90 0 226 'experimental' => {pp=>1, core=>0}, # only core in 5.020+, so we note it as 0
126             'List::Util' => {pp=>0, core=>1},
127             'Module::List::More' => {pp=>1, core=>0},
128             'PERLANCAR::Module::List' => {pp=>1, core=>0},
129             'Regexp::From::String' => {pp=>1, core=>0},
130             'Scalar::Util::Numeric' => {pp=>0, core=>0},
131             'Scalar::Util::Numeric::PP' => {pp=>1, core=>0},
132             'Scalar::Util' => {pp=>0, core=>1},
133             'Storable' => {pp=>0, core=>1},
134             'String::Wildcard::Bash' => {pp=>1, core=>0},
135             'Time::Duration::Parse::AsHash' => {pp=>1, core=>0},
136             'Time::Local' => {pp=>1, core=>1},
137             'Time::Moment' => {pp=>0, core=>0},
138             'Time::Piece' => {pp=>0, core=>1},
139             'warnings' => {pp=>1, core=>1},
140             );
141              
142             my ($self, $cd, $name, $extra_keys, $allow_duplicate) = @_;
143              
144             if (exists $extra_keys->{core}) {
145             $known_modules{$name}{core} = $extra_keys->{core};
146             }
147              
148             if (exists $extra_keys->{pp}) {
149             $known_modules{$name}{pp} = $extra_keys->{pp};
150             }
151              
152             if ($extra_keys->{phase} eq 'runtime') {
153 14100     14100 0 25632 if ($cd->{args}{no_modules}) {
154             die "BUG: Use of module '$name' when compile option no_modules=1";
155 14100 50       32921 }
156 0         0  
157             if ($cd->{args}{whitelist_modules} && grep { $_ eq $name } @{ $cd->{args}{whitelist_modules} }) {
158             goto PASS;
159 14100 50       28084 }
160 0         0  
161             if ($cd->{args}{pp}) {
162             if (!$known_modules{$name}) {
163 14100 100       30251 die "BUG: Haven't noted about Perl module '$name' as being pp/xs";
164 7653 50       18832 } elsif (!$known_modules{$name}{pp}) {
165 0         0 die "Use of XS module '$name' when compile option pp=1";
166             }
167             }
168 7653 50 33     20589  
  0         0  
  0         0  
169 0         0 if ($cd->{args}{core}) {
170             if (!$known_modules{$name}) {
171             die "BUG: Haven't noted about Perl module '$name' as being core/non-core";
172 7653 100       14660 } elsif (!$known_modules{$name}{core}) {
173 80 50       277 die "Use of non-core module '$name' when compile option core=1";
    50          
174 0         0 }
175             }
176 0         0  
177             if ($cd->{args}{core_or_pp}) {
178             if (!$known_modules{$name}) {
179             die "BUG: Haven't noted about Perl module '$name' as being core/non-core or pp/xs";
180 7653 100       16121 } elsif (!$known_modules{$name}{pp} && !$known_modules{$name}{core}) {
181 40 50       125 die "Use of non-core XS module '$name' when compile option core_or_pp=1";
    50          
182 0         0 }
183             }
184 0         0 }
185             PASS:
186             $self->SUPER::add_module($cd, $name, $extra_keys, $allow_duplicate);
187             }
188 7653 100       16208  
189 80 50 33     295 my ($self, $cd, $name, $import_terms) = @_;
    50          
190 0         0 my $use_statement = "use $name".
191             ($import_terms && @$import_terms ? " (".(join ",", @$import_terms).")" : "");
192 0         0  
193             # avoid duplicate use statement
194             for my $mod (@{ $cd->{modules} }) {
195             next unless $mod->{phase} eq 'runtime';
196             return if $mod->{use_statement} &&
197 14100         36880 $mod->{use_statement} eq $use_statement;
198             }
199              
200             $self->add_runtime_module(
201 17     17 1 30 $cd,
202 17 50 33     61 $name,
203             {
204             use_statement => $use_statement,
205             },
206 17         28 1, # allow duplicate
  17         36  
207 69 100       133 );
208             }
209 39 100 100     101  
210             my ($self, $cd, $name, $import_terms) = @_;
211              
212             my $use_statement = "no $name".
213 12         49 ($import_terms && @$import_terms ? " (".(join ",", @$import_terms).")" : "");
214              
215             # avoid duplicate use statement
216             for my $mod (@{ $cd->{modules} }) {
217             next unless $mod->{phase} eq 'runtime';
218             return if $mod->{use_statement} &&
219             $mod->{use_statement} eq $use_statement;
220             }
221              
222             $self->add_runtime_module(
223 5020     5020 1 9699 $cd,
224             $name,
225 5020 50 33     26280 {
226             use_statement => $use_statement,
227             },
228             1, # allow duplicate
229 5020         7758 );
  5020         11192  
230 330 50       737 }
231              
232 330 50 33     1355 # add Scalar::Util::Numeric module
233             my ($self, $cd) = @_;
234             if ($cd->{args}{pp} || $cd->{args}{core_or_pp} ||
235             !eval { require Scalar::Util::Numeric; 1 }) {
236 4690         19074 $cd->{_sun_module} = 'Scalar::Util::Numeric::PP';
237             } elsif ($cd->{args}{core}) {
238             # just to make sure compilation will fail if we mistakenly use a sun
239             # module
240             $cd->{_sun_module} = 'Foo';
241             } else {
242             $cd->{_sun_module} = 'Scalar::Util::Numeric';
243             }
244             $self->add_runtime_module($cd, $cd->{_sun_module});
245             }
246              
247 1768     1768 1 3652 # evaluate all terms, then return the last term. user has to make sure all the
248 1768 100 100     7553 # terms are properly parenthesized if it contains operator with precedence less
    50 66        
249 1688         11448 # than the list operator.
  1688         11321  
250 80         134 my ($self, @t) = @_;
251             "(".join(", ", @t).")";
252             }
253              
254 0         0 my ($self, $t) = @_;
255             "defined($t)";
256 1688         4043 }
257              
258 1768         5598 my ($self, @t) = @_;
259             "[".join(",", @t)."]";
260             }
261              
262             my ($self, $at, $idxt) = @_;
263             "$at->\[$idxt]";
264             }
265 1382     1382 0 3019  
266 1382         7859 my ($self, $at, $idxt) = @_;
267             "$at->\[-1]";
268             }
269              
270 5115     5115 0 10307 my ($self, $at, $elt) = @_;
271 5115         18411 "push(\@{$at}, $elt)";
272             }
273              
274             my ($self, $at, $elt) = @_;
275 9606     9606 0 22900 "pop(\@{$at})";
276 9606         29329 }
277              
278             my ($self, $et) = @_;
279             join(
280 658     658 0 1278 "",
281 658         2006 "[",
282             $self->expr_push('$_sahv_dpath', $self->literal(undef)), ", ", # 0
283             "scalar", $self->enclose_paren($et), ", ", #1 ('scalar' to avoid list flattening)
284             $self->expr_pop('$_sahv_dpath'), # 2
285 0     0 0 0 "]->[1]",
286 0         0 );
287             }
288              
289             my ($self, $t) = @_;
290 86     86 0 2014 '(@$_sahv_dpath ? \'@\'.join("",map {"[$_]"} @$_sahv_dpath).": " : "") . ' . $t;
291 86         290 }
292              
293             # $l = $r
294             my ($self, $l, $r) = @_;
295 612     612 0 1158 "($l = $r)";
296 612         2206 }
297              
298             # $l //= $r
299             my ($self, $l, $r) = @_;
300 86     86 0 180 "($l //= $r)";
301 86         223 }
302              
303             my ($self, $et, $err_expr) = @_;
304             "($et //= $err_expr)";
305             }
306              
307             my ($self, $et, $k, $err_expr) = @_;
308             "($et\->{$k}{join('/',\@\$_sahv_dpath)} //= $err_expr)";
309             }
310              
311             my ($self, $et, $err_expr) = @_;
312 4095     4095 0 8155 "($et = undef, 1)";
313 4095         10948 }
314              
315             my ($self, $et) = @_;
316             "(delete($et\->{errors}{join('/',\@\$_sahv_dpath)}), 1)";
317             }
318 1821     1821 0 4190  
319 1821         6434 # $cond_term ? $true_term : $false_term
320             my ($self, $cond_term, $true_term, $false_term) = @_;
321             "$cond_term ? $true_term : $false_term";
322             }
323              
324 91     91 0 220 my ($self, $cd, @expr) = @_;
325 91         300  
326             "log_trace('[sah validator](spath=%s) %s', " .
327             $self->literal($cd->{spath}).", " . join(", ", @expr) . ")";
328             }
329 13086     13086 0 238473  
330 13086         35387 # convert Expr expression to perl expression
331             require Language::Expr;
332              
333             my ($self, $cd, $expr) = @_;
334 3710     3710 0 6764  
335 3710         12003 $self->add_runtime_use($cd, 'boolean');
336             "(" . Language::Expr->new->get_compiler('perl')->compile($expr) . ")";
337             }
338              
339 202     202 0 490 # wrap statements into an expression
340 202         662 my ($self, $code) = @_;
341             join(
342             "",
343             "do {\n",
344 202     202 0 534 __indent(
345 202         599 $self->indent_character,
346             $code,
347             ),
348             "}",
349             );
350 1468     1468 0 3601 }
351 1468         5010  
352             # whether block is implemented using function
353              
354             my ($self, $v, $vt) = @_;
355 0     0 0 0 if ($vt eq 'undef') {
356             "my \$$v;";
357             } else {
358 0         0 "my \$$v = $vt;";
359             }
360             }
361              
362             my ($self, $args, $code) = @_;
363 17     17 0 961  
364             join(
365 17         679 "",
366             "sub {\n",
367 17         47 __indent(
368 17         96 $self->indent_character,
369             join(
370             "",
371             ("my (".join(", ", @$args).") = \@_;\n") x !!@$args,
372             $code,
373 5258     5258 0 9748 ),
374 5258         14404 ),
375             "}"
376             );
377             }
378              
379             # enclose $stmt in an eval/try block, return true if succeeds, false if error
380             # was thrown. XXX error message was not recorded yet.
381             my ($self, $stmt) = @_;
382             "(eval { $stmt }, !\$@)";
383             }
384              
385             # Storable (fast, core) is not chosen because i cannot make it to dump 3 and "3"
386 607     607 0 2453 # as "3". some other inconveniences (but not deal breaker): 1) only accepts
387             # references so we need to freeze \$foo or [$foo] instead of just $foo; 2) need
388             # to set $Storable::canonical to true, otherwise hash keys are not ordered.
389 10943     10943 0 180328  
390 10943 100       18536 my ($self, $cd, $t) = @_;
391 1473         7946 my $dump_module = $cd->{args}{dump_module};
392             if ($dump_module eq 'Data::Dumper') {
393 9470         36863 "Data::Dumper->new([$t])->Terse(1)->Indent(0)->Sortkeys(1)->Dump";
394             } elsif ($dump_module eq 'Data::Dmp') {
395             "Data::Dmp::dmp($t)";
396             } else {
397             $self->_die($cd, "Unknown dump module '$dump_module'") if $@;
398 4691     4691 0 9549 }
399             }
400 4691         14101  
401             my ($self, $mod_record) = @_;
402              
403             if ($mod_record->{use_statement}) {
404             return "$mod_record->{use_statement};";
405             } else {
406             "require $mod_record->{name};";
407             }
408             }
409              
410             my ($self) = @_;
411             'use Log::ger;';
412             }
413              
414             my ($self, $ht, $kt, $vt) = @_;
415             "$ht\->{$kt} = $vt;";
416             }
417              
418 0     0 0 0 my $self = shift;
419 0         0 if (@_) {
420             "return($_[0]);";
421             } else {
422             'return;';
423             }
424             }
425              
426             # currently unused
427             my ($self, $name) = @_;
428 1226     1226 0 1969 "do { no strict 'refs'; \\&{" . $self->literal($name) . "} }";
429 1226         1713 }
430 1226 50       1811  
    0          
431 1226         4896 my ($self, $name, $args) = @_;
432             "$name(".join(", ", @$args).")";
433 0         0 }
434              
435 0 0       0 my ($self, $cd, $schema_name) = @_;
436             my $subname = $self->cached_validator_subname($cd, $schema_name);
437             $self->expr_call_sub($subname, [$cd->{data_term}]);
438             }
439              
440 7185     7185 0 11197 my ($self, %args) = @_;
441              
442 7185 100       14686 $self->check_compile_args(\%args);
443 4663         17375  
444             my $aref = delete $args{accept_ref};
445 2522         9561 if ($aref) {
446             $args{var_term} = '$ref_'.$args{data_name};
447             $args{data_term} = '$$ref_'.$args{data_name};
448             } else {
449             $args{var_term} = '$'.$args{data_name};
450 4691     4691 0 9447 $args{data_term} = '$'.$args{data_name};
451 4691         11492 }
452              
453             $self->SUPER::expr_validator_sub(%args);
454             }
455 4691     4691 0 113831  
456 4691         14790 require Regexp::Stringify;
457              
458             my ($self, $cd, $str) = @_;
459              
460 23455     23455 0 32916 my $re;
461 23455 50       36495 if (ref($str) eq 'Regexp') {
462 23455         73132 $re = $str;
463             } else {
464 0         0 eval { $re = qr/$str/ };
465             $self->_die($cd, "Invalid regex $str: $@") if $@;
466             }
467              
468             Regexp::Stringify::stringify_regexp(regexp=>$re, plver=>5.010);
469             }
470 0     0 0 0  
471 0         0 # check if sub named $name is defined and return true if it's the case
472             my ($self, $name) = @_;
473             defined &{$name};
474             }
475 0     0 0 0  
476 0         0 my ($self, $cd, $schema_name) = @_;
477             local $cd->{args}{return_type} = 'bool_valid'; # XXX temp
478             die unless $cd->{args}{return_type} =~ /\A(bool|str|hash)_/;
479             "Data::Sah::_GeneratedValidators::Returns".ucfirst($1)."::".$schema_name;
480 0     0 0 0 }
481 0         0  
482 0         0 my ($self, $cd, $schema_name) = @_;
483             my $subname = $self->cached_validator_subname($cd, $schema_name);
484             return if defined &{$subname};
485             log_trace "Generating cached validator for base schema %s", $schema_name;
486 4724     4724 0 14543 my $sub_code = $self->expr_validator_sub(
487             %{$cd->{args}},
488 4724         17318 schema => $schema_name,
489             schema_is_normalized => 0,
490 4724         10989 data_name => "data",
491 4724 100       10385 resolve_opts=>{allow_base_with_no_additional_clauses=>0},
492 6         16 return_type => "bool_valid", # XXX temp
493 6         20 );
494             my $code = "*$subname = $sub_code;";
495 4718         10887 eval $code; ## no critic: BuiltinFunctions::ProhibitStringyEval
496 4718         8158 $self->_die($cd, "Cannot generate cached validator for '$schema_name': $@") if $@;
497             }
498              
499 4724         23921 1;
500             # ABSTRACT: Compile Sah schema to Perl code
501              
502              
503 222     222   2069 =pod
504              
505 222         1810 =encoding UTF-8
506              
507 222         307 =head1 NAME
508 222 100       531  
509 2         2 Data::Sah::Compiler::perl - Compile Sah schema to Perl code
510              
511 220         372 =head1 VERSION
  220         1757  
512 220 100       635  
513             This document describes version 0.913 of Data::Sah::Compiler::perl (from Perl distribution Data-Sah), released on 2022-09-30.
514              
515 219         676 =head1 SYNOPSIS
516              
517             # see Data::Sah
518              
519             =head1 DESCRIPTION
520 0     0 0    
521 0           Derived from L<Data::Sah::Compiler::Prog>.
  0            
522              
523             =for Pod::Coverage BUILD ^(after_.+|before_.+|name|expr|true|false|literal|expr_.+|stmt_.+|block_uses_sub|sub_defined|cached_validator_subname|gen_cached_validator)$
524              
525 0     0 0   =head1 VARIABLES
526 0            
527 0 0         =head2 $PP => bool
528 0            
529             Set default for C<pp> compile argument. Takes precedence over environment
530             C<DATA_SAH_PP>.
531              
532 0     0 0   =head2 $CORE => bool
533 0            
534 0 0         Set default for C<core> compile argument. Takes precedence over environment
  0            
535 0           C<DATA_SAH_CORE>.
536              
537 0           =head2 $CORE_OR_PP => bool
  0            
538              
539             Set default for C<core_or_pp> compile argument. Takes precedence over
540             environment C<DATA_SAH_CORE_OR_PP>.
541              
542             =head2 $NO_MODULES => bool
543              
544 0           Set default for C<no_modules> compile argument. Takes precedence over
545 0           environment C<DATA_SAH_NO_MODULES>.
546 0 0          
547             =head1 DEVELOPER NOTES
548              
549             To generate expression code that says "all subexpression must be true", you can
550             do:
551              
552             !defined(List::Util::first(sub { blah($_) }, "value", ...))
553              
554             This is a bit harder to read than:
555              
556             !grep { !blah($_) } "value", ...
557              
558             but has the advantage of the ability to shortcut on the first item that fails.
559              
560             Similarly, to say "at least one subexpression must be true":
561              
562             defined(List::Util::first(sub { blah($_) }, "value", ...))
563              
564             which can shortcut in contrast to:
565              
566             grep { blah($_) } "value", ...
567              
568             =head1 METHODS
569              
570             =head2 new() => OBJ
571              
572             =head3 Compilation data
573              
574             This subclass adds the following compilation data (C<$cd>).
575              
576             Keys which contain compilation result:
577              
578             =over
579              
580             =back
581              
582             =head2 $c->comment($cd, @args) => STR
583              
584             Generate a comment. For example, in perl compiler:
585              
586             $c->comment($cd, "123"); # -> "# 123\n"
587              
588             Will return an empty string if compile argument C<comment> is set to false.
589              
590             =head2 $c->compile(%args) => RESULT
591              
592             Aside from arguments known by the base class (L<Data::Sah::Compiler::Prog>),
593             this class supports these arguments:
594              
595             =over
596              
597             =item * pp
598              
599             Bool, default false. If set to true, will avoid the use of XS modules in the
600             generated code and will opt instead to use pure-perl modules.
601              
602             =item * core
603              
604             Bool, default false. If set to true, will avoid the use of non-core modules in
605             the generated code and will opt instead to use core modules.
606              
607             =item * core_or_pp
608              
609             Bool, default false. If set to true, will stick to using only core or PP modules
610             in the generated code.
611              
612             =item * whitelist_modules
613              
614             Array of str. When C<pp>/C<core>/C<core_or_pp> option is set to true, the use of
615             non-appropriate modules will cause failure. However, you can pass a list of
616             modules that are allowed nevertheless.
617              
618             =back
619              
620             =head2 $c->add_runtime_use($cd, $module [, \@import_terms ])
621              
622             This is like C<add_runtime_module()>, but indicate that C<$module> needs to be
623             C<use>-d in the generated code (for example, Perl pragmas). Normally if
624             C<add_runtime_module()> is used, the generated code will use C<require>.
625              
626             If you use C<< $c->add_runtime_use($cd, 'foo') >>, this code will be generated:
627              
628             use foo;
629              
630             If you use C<< $c->add_runtime_use($cd, 'foo', ["'a'", "'b'", "123"]) >>, this code will
631             be generated:
632              
633             use foo ('a', 'b', 123);
634              
635             If you use C<< $c->add_runtime_use($cd, 'foo', []) >>, this code will be generated:
636              
637             use foo ();
638              
639             The generated statement will be added at the top (top-level lexical scope) and
640             duplicates are ignored. To generate multiple and lexically-scoped C<use> and
641             C<no> statements, e.g. like below, currently you can generate them manually:
642              
643             if (blah) {
644             no warnings;
645             ...
646             }
647              
648             =head2 $c->add_runtime_no($cd, $module [, \@import_terms ])
649              
650             This is the counterpart of C<add_runtime_use()>, to generate C<no foo> statement.
651              
652             See also: C<add_runtime_use()>.
653              
654             =head2 $c->add_sun_module($cd)
655              
656             Add L<Scalar::Util::Numeric> module, or L<Scalar::Util::Numeric::PP> when C<pp>
657             compile argument is true.
658              
659             =head1 ENVIRONMENT
660              
661             =head2 DATA_SAH_PP => bool
662              
663             Set default for C<pp> compile argument.
664              
665             =head2 DATA_SAH_CORE => bool
666              
667             Set default for C<core> compile argument.
668              
669             =head2 DATA_SAH_CORE_OR_PP => bool
670              
671             Set default for C<core_or_pp> compile argument.
672              
673             =head2 DATA_SAH_NO_MODULES => bool
674              
675             Set default for C<no_modules> compile argument.
676              
677             =head1 HOMEPAGE
678              
679             Please visit the project's homepage at L<https://metacpan.org/release/Data-Sah>.
680              
681             =head1 SOURCE
682              
683             Source repository is at L<https://github.com/perlancar/perl-Data-Sah>.
684              
685             =head1 AUTHOR
686              
687             perlancar <perlancar@cpan.org>
688              
689             =head1 CONTRIBUTING
690              
691              
692             To contribute, you can send patches by email/via RT, or send pull requests on
693             GitHub.
694              
695             Most of the time, you don't need to build the distribution yourself. You can
696             simply modify the code, then test via:
697              
698             % prove -l
699              
700             If you want to build the distribution (e.g. to try to install it locally on your
701             system), you can install L<Dist::Zilla>,
702             L<Dist::Zilla::PluginBundle::Author::PERLANCAR>,
703             L<Pod::Weaver::PluginBundle::Author::PERLANCAR>, and sometimes one or two other
704             Dist::Zilla- and/or Pod::Weaver plugins. Any additional steps required beyond
705             that are considered a bug and can be reported to me.
706              
707             =head1 COPYRIGHT AND LICENSE
708              
709             This software is copyright (c) 2022, 2021, 2020, 2019, 2018, 2017, 2016, 2015, 2014, 2013, 2012 by perlancar <perlancar@cpan.org>.
710              
711             This is free software; you can redistribute it and/or modify it under
712             the same terms as the Perl 5 programming language system itself.
713              
714             =head1 BUGS
715              
716             Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Data-Sah>
717              
718             When submitting a bug or request, please include a test-file or a
719             patch to an existing test-file that illustrates the bug or desired
720             feature.
721              
722             =cut