summaryrefslogtreecommitdiff
path: root/t/op/coreinline.t
diff options
context:
space:
mode:
Diffstat (limited to 't/op/coreinline.t')
-rw-r--r--t/op/coreinline.t108
1 files changed, 108 insertions, 0 deletions
diff --git a/t/op/coreinline.t b/t/op/coreinline.t
new file mode 100644
index 0000000000..ce3ce37c4e
--- /dev/null
+++ b/t/op/coreinline.t
@@ -0,0 +1,108 @@
+#!./perl
+
+BEGIN {
+ chdir 't' if -d 't';
+ @INC = qw(. ../lib);
+ require "test.pl";
+ skip_all_without_dynamic_extension('B');
+ $^P |= 0x100;
+}
+
+use B::Deparse;
+my $bd = new B::Deparse '-p';
+
+my %unsupported = map +($_=>1), qw (CORE and cmp dump eq ge gt le
+ getprotobynumber lt ne not or x xor);
+my %args_for = (
+ dbmopen => '%1,$2,$3',
+ dbmclose => '%1',
+);
+
+use File::Spec::Functions;
+my $keywords_file = catfile(updir,'regen','keywords.pl');
+open my $kh, $keywords_file
+ or die "$0 cannot open $keywords_file: $!";
+while(<$kh>) {
+ if (m?__END__?..${\0} and /^[+-]/) {
+ chomp(my $word = $');
+ if($& eq '+' || $unsupported{$word}) {
+ $tests ++;
+ ok !defined &{\&{"CORE::$word"}}, "no CORE::$word";
+ }
+ else {
+ $tests += 3;
+
+ my $proto = prototype "CORE::$word";
+ *{"my$word"} = \&{"CORE::$word"};
+ is prototype \&{"my$word"}, $proto, "prototype of &CORE::$word";
+
+ CORE::state $protochar = qr/([^\\]|\\(?:[^[]|\[[^]]+\]))/;
+ my $numargs =
+ () = $proto =~ s/;.*//r =~ /\G$protochar/g;
+ my $code =
+ "#line 1 This-line-makes-__FILE__-easier-to-test.
+ sub { () = (my$word("
+ . ($args_for{$word} || join ",", map "\$$_", 1..$numargs)
+ . "))}";
+ my $core = $bd->coderef2text(eval $code =~ s/my/CORE::/r or die);
+ my $my = $bd->coderef2text(eval $code or die);
+ is $my, $core, "inlinability of CORE::$word with parens";
+
+ $code =
+ "#line 1 This-line-makes-__FILE__-easier-to-test.
+ sub { () = (my$word "
+ . ($args_for{$word} || join ",", map "\$$_", 1..$numargs)
+ . ")}";
+ $core = $bd->coderef2text(eval $code =~ s/my/CORE::/r or die);
+ $my = $bd->coderef2text(eval $code or die);
+ is $my, $core, "inlinability of CORE::$word without parens";
+
+ # High-precedence tests
+ my $hpcode;
+ if (!$proto && defined $proto) { # nullary
+ $hpcode = "sub { () = my$word + 1 }";
+ }
+ elsif ($proto =~ /^;?$protochar\z/) { # unary
+ $hpcode = "sub { () = my$word "
+ . ($args_for{$word}||'$a') . ' > $b'
+ .'}';
+ }
+ if ($hpcode) {
+ $tests ++;
+ $core = $bd->coderef2text(eval $hpcode =~ s/my/CORE::/r or die);
+ $my = $bd->coderef2text(eval $hpcode or die);
+ is $my, $core, "precedence of CORE::$word without parens";
+ }
+
+ next if ($proto =~ /\@/);
+ # These ops currently accept any number of args, despite their
+ # prototypes, if they have any:
+ next if $word =~ /^(?:chom?p|exec|keys|each|read(?:lin|pip)e|reset
+ |system|values|l?stat)/x;
+
+ $tests ++;
+ $code =
+ "sub { () = (my$word("
+ . (
+ $args_for{$word}
+ ? $args_for{$word}.',$7'
+ : join ",", map "\$$_", 1..$numargs+5+(
+ $proto =~ /;/
+ ? () = $' =~ /\G$protochar/g
+ : 0
+ )
+ )
+ . "))}";
+ eval $code;
+ like $@, qr/^Too many arguments for $word/,
+ "inlined CORE::$word with too many args"
+ or warn $code;
+
+ }
+ }
+}
+
+is curr_test, $tests+1, 'right number of tests';
+done_testing;
+
+CORE::__END__