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   385 use strict;
  22         67  
4 22     22   100 use warnings;
  22         46  
  22         393  
5 22     22   83 use Log::ger;
  22         40  
  22         471  
6 22     22   31371  
  22         970  
  22         95  
7             use Data::Dmp qw(dmp);
8 22     22   14036 use Mo qw(build default);
  22         37756  
  22         1321  
9 22     22   142  
  22         41  
  22         112  
10             extends 'Data::Sah::Compiler::Prog';
11              
12             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
13             our $DATE = '2022-08-20'; # DATE
14             our $DIST = 'Data-Sah'; # DIST
15             our $VERSION = '0.912'; # 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   80625  
26 9949   50     38070 my $ibl = $opts->{indent_blank_lines} // 1;
27             my $fli = $opts->{first_line_indent} // $indent;
28 9949   50     27803 my $sli = $opts->{subsequent_lines_indent} // $indent;
29 9949   33     25589 #say "D:ibl=<$ibl>, fli=<$fli>, sli=<$sli>";
30 9949   33     25704  
31             my $i = 0;
32             $str =~ s/^([^\r\n]?)/$i++; !$ibl && !$1 ? "$1" : $i==1 ? "$fli$1" : "$sli$1"/egm;
33 9949         12367 $str;
34 9949 100 33     39244 }
  221410 50       238534  
  221410         665767  
35 9949         67045 # END COPIED FROM String::Indent
36              
37             my ($self, $args) = @_;
38              
39             $self->comment_style('shell');
40 4751     4751 0 210791 $self->indent_character(" " x 4);
41             $self->var_sigil('$');
42 4751         14430 $self->concat_op(".");
43 4751         31240 }
44 4751         35565  
45 4751         19589  
46             dmp($_[1]);
47             }
48 25512     25512 0 75265  
49             my ($self, %args) = @_;
50              
51 40726     40726 0 102324 #$self->expr_compiler->compiler->hook_var(
52             # sub {
53             # $_[0];
54             # }
55 5060     5060 1 37127 #);
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     19854  
82             $self->SUPER::compile(%args);
83 5060   66     31758 }
      50        
      100        
84 5060   66     31712  
      50        
      100        
85 5060   66     26877 my ($self, %args) = @_;
      50        
      100        
86 5060   66     34045  
      50        
      100        
87             my $cd = $self->SUPER::init_cd(%args);
88 5060         28272  
89             $self->add_runtime_no($cd, 'warnings', ["'void'"]) unless $cd->{args}{no_modules};
90              
91             $cd;
92 5060     5060 0 32872 }
93              
94 5060         26933 require Data::Cmp;
95              
96 5060 100       28566 my ($self, $cd) = @_;
97              
98 5060         27049 # 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 31404  
103             my $nschema = $cd->{nschema};
104 5060         24038 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       17404 return 99;
110             }
111 1908         3413  
112 1908         3396 return;
113 1908 50       8609 }
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         121461 '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 40954 'DateTime::Format::Alami::ID' => {pp=>1, core=>0},
124             'DateTime::Format::Natural' => {pp=>1, core=>0},
125 90     90 0 207 '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 14092     14092 0 26600 if ($cd->{args}{no_modules}) {
154             die "BUG: Use of module '$name' when compile option no_modules=1";
155 14092 50       31932 }
156 0         0  
157             if ($cd->{args}{whitelist_modules} && grep { $_ eq $name } @{ $cd->{args}{whitelist_modules} }) {
158             goto PASS;
159 14092 50       28837 }
160 0         0  
161             if ($cd->{args}{pp}) {
162             if (!$known_modules{$name}) {
163 14092 100       30216 die "BUG: Haven't noted about Perl module '$name' as being pp/xs";
164 7653 50       15408 } 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     17409  
  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       15726 } elsif (!$known_modules{$name}{core}) {
173 80 50       250 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       16859 } elsif (!$known_modules{$name}{pp} && !$known_modules{$name}{core}) {
181 40 50       112 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       15623  
189 80 50 33     297 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 14092         35179 $mod->{use_statement} eq $use_statement;
198             }
199              
200             $self->add_runtime_module(
201 17     17 1 31 $cd,
202 17 50 33     61 $name,
203             {
204             use_statement => $use_statement,
205             },
206 17         21 1, # allow duplicate
  17         36  
207 69 100       117 );
208             }
209 39 100 100     103  
210             my ($self, $cd, $name, $import_terms) = @_;
211              
212             my $use_statement = "no $name".
213 12         48 ($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 12554 $cd,
224             $name,
225 5020 50 33     28309 {
226             use_statement => $use_statement,
227             },
228             1, # allow duplicate
229 5020         7803 );
  5020         12181  
230 330 50       736 }
231              
232 330 50 33     1440 # 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         21088 $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 3426 # evaluate all terms, then return the last term. user has to make sure all the
248 1768 100 100     8124 # terms are properly parenthesized if it contains operator with precedence less
    50 66        
249 1688         11657 # than the list operator.
  1688         11251  
250 80         136 my ($self, @t) = @_;
251             "(".join(", ", @t).")";
252             }
253              
254 0         0 my ($self, $t) = @_;
255             "defined($t)";
256 1688         3414 }
257              
258 1768         6233 my ($self, @t) = @_;
259             "[".join(",", @t)."]";
260             }
261              
262             my ($self, $at, $idxt) = @_;
263             "$at->\[$idxt]";
264             }
265 1382     1382 0 3494  
266 1382         8355 my ($self, $at, $idxt) = @_;
267             "$at->\[-1]";
268             }
269              
270 5115     5115 0 10245 my ($self, $at, $elt) = @_;
271 5115         17868 "push(\@{$at}, $elt)";
272             }
273              
274             my ($self, $at, $elt) = @_;
275 9606     9606 0 22353 "pop(\@{$at})";
276 9606         29291 }
277              
278             my ($self, $et) = @_;
279             join(
280 658     658 0 1220 "",
281 658         1650 "[",
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 1996 '(@$_sahv_dpath ? \'@\'.join("",map {"[$_]"} @$_sahv_dpath).": " : "") . ' . $t;
291 86         322 }
292              
293             # $l = $r
294             my ($self, $l, $r) = @_;
295 612     612 0 1147 "($l = $r)";
296 612         2097 }
297              
298             # $l //= $r
299             my ($self, $l, $r) = @_;
300 86     86 0 221 "($l //= $r)";
301 86         236 }
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 7888 "($et = undef, 1)";
313 4095         10680 }
314              
315             my ($self, $et) = @_;
316             "(delete($et\->{errors}{join('/',\@\$_sahv_dpath)}), 1)";
317             }
318 1821     1821 0 4327  
319 1821         6470 # $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 198 my ($self, $cd, @expr) = @_;
325 91         333  
326             "log_trace('[sah validator](spath=%s) %s', " .
327             $self->literal($cd->{spath}).", " . join(", ", @expr) . ")";
328             }
329 13086     13086 0 239216  
330 13086         36269 # convert Expr expression to perl expression
331             require Language::Expr;
332              
333             my ($self, $cd, $expr) = @_;
334 3710     3710 0 7482  
335 3710         13494 $self->add_runtime_use($cd, 'boolean');
336             "(" . Language::Expr->new->get_compiler('perl')->compile($expr) . ")";
337             }
338              
339 202     202 0 488 # wrap statements into an expression
340 202         591 my ($self, $code) = @_;
341             join(
342             "",
343             "do {\n",
344 202     202 0 497 __indent(
345 202         588 $self->indent_character,
346             $code,
347             ),
348             "}",
349             );
350 1460     1460 0 4089 }
351 1460         5289  
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 1553  
364             join(
365 17         584 "",
366             "sub {\n",
367 17         48 __indent(
368 17         86 $self->indent_character,
369             join(
370             "",
371             ("my (".join(", ", @$args).") = \@_;\n") x !!@$args,
372             $code,
373 5258     5258 0 10323 ),
374 5258         13815 ),
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 2683 # 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 181028  
390 10943 100       19716 my ($self, $cd, $t) = @_;
391 1473         8988 my $dump_module = $cd->{args}{dump_module};
392             if ($dump_module eq 'Data::Dumper') {
393 9470         39786 "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 12497 }
399             }
400 4691         14956  
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 1898 "do { no strict 'refs'; \\&{" . $self->literal($name) . "} }";
429 1226         1662 }
430 1226 50       1854  
    0          
431 1226         4430 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 12045 my ($self, %args) = @_;
441              
442 7185 100       14410 $self->check_compile_args(\%args);
443 4663         18998  
444             my $aref = delete $args{accept_ref};
445 2522         10945 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 9018 $args{data_term} = '$'.$args{data_name};
451 4691         12336 }
452              
453             $self->SUPER::expr_validator_sub(%args);
454             }
455 4691     4691 0 115085  
456 4691         14117 require Regexp::Stringify;
457              
458             my ($self, $cd, $str) = @_;
459              
460 23455     23455 0 30563 my $re;
461 23455 50       34308 if (ref($str) eq 'Regexp') {
462 23455         79506 $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 15730 my $sub_code = $self->expr_validator_sub(
487             %{$cd->{args}},
488 4724         17998 schema => $schema_name,
489             schema_is_normalized => 0,
490 4724         10400 data_name => "data",
491 4724 100       11339 resolve_opts=>{allow_base_with_no_additional_clauses=>0},
492 6         22 return_type => "bool_valid", # XXX temp
493 6         16 );
494             my $code = "*$subname = $sub_code;";
495 4718         10420 eval $code; ## no critic: BuiltinFunctions::ProhibitStringyEval
496 4718         9248 $self->_die($cd, "Cannot generate cached validator for '$schema_name': $@") if $@;
497             }
498              
499 4724         25071 1;
500             # ABSTRACT: Compile Sah schema to Perl code
501              
502              
503 222     222   2207 =pod
504              
505 222         1923 =encoding UTF-8
506              
507 222         322 =head1 NAME
508 222 100       643  
509 2         4 Data::Sah::Compiler::perl - Compile Sah schema to Perl code
510              
511 220         430 =head1 VERSION
  220         1941  
512 220 100       737  
513             This document describes version 0.912 of Data::Sah::Compiler::perl (from Perl distribution Data-Sah), released on 2022-08-20.
514              
515 219         914 =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