|
|
64337f |
diff -up constant-1.27/lib/constant.pm.127 constant-1.27/lib/constant.pm
|
|
|
64337f |
--- constant-1.27/lib/constant.pm.127 2015-04-27 13:39:46.613767559 +0200
|
|
|
64337f |
+++ constant-1.27/lib/constant.pm 2015-01-27 23:47:42.000000000 +0100
|
|
|
64337f |
@@ -3,8 +3,8 @@ use 5.008;
|
|
|
64337f |
use strict;
|
|
|
64337f |
use warnings::register;
|
|
|
64337f |
|
|
|
64337f |
-use vars qw($VERSION %declared);
|
|
|
64337f |
-$VERSION = '1.27';
|
|
|
64337f |
+our $VERSION = '1.33';
|
|
|
64337f |
+our %declared;
|
|
|
64337f |
|
|
|
64337f |
#=======================================================================
|
|
|
64337f |
|
|
|
64337f |
@@ -24,13 +24,24 @@ my $boolean = qr/^[01]?\z/;
|
|
|
64337f |
BEGIN {
|
|
|
64337f |
# We'd like to do use constant _CAN_PCS => $] > 5.009002
|
|
|
64337f |
# but that's a bit tricky before we load the constant module :-)
|
|
|
64337f |
- # By doing this, we save 1 run time check for *every* call to import.
|
|
|
64337f |
- no strict 'refs';
|
|
|
64337f |
+ # By doing this, we save several run time checks for *every* call
|
|
|
64337f |
+ # to import.
|
|
|
64337f |
my $const = $] > 5.009002;
|
|
|
64337f |
- *_CAN_PCS = sub () {$const};
|
|
|
64337f |
-
|
|
|
64337f |
my $downgrade = $] < 5.015004; # && $] >= 5.008
|
|
|
64337f |
- *_DOWNGRADE = sub () { $downgrade };
|
|
|
64337f |
+ my $constarray = exists &_make_const;
|
|
|
64337f |
+ if ($const) {
|
|
|
64337f |
+ Internals::SvREADONLY($const, 1);
|
|
|
64337f |
+ Internals::SvREADONLY($downgrade, 1);
|
|
|
64337f |
+ $constant::{_CAN_PCS} = \$const;
|
|
|
64337f |
+ $constant::{_DOWNGRADE} = \$downgrade;
|
|
|
64337f |
+ $constant::{_CAN_PCS_FOR_ARRAY} = \$constarray;
|
|
|
64337f |
+ }
|
|
|
64337f |
+ else {
|
|
|
64337f |
+ no strict 'refs';
|
|
|
64337f |
+ *{"_CAN_PCS"} = sub () {$const};
|
|
|
64337f |
+ *{"_DOWNGRADE"} = sub () { $downgrade };
|
|
|
64337f |
+ *{"_CAN_PCS_FOR_ARRAY"} = sub () { $constarray };
|
|
|
64337f |
+ }
|
|
|
64337f |
}
|
|
|
64337f |
|
|
|
64337f |
#=======================================================================
|
|
|
64337f |
@@ -46,13 +57,13 @@ sub import {
|
|
|
64337f |
return unless @_; # Ignore 'use constant;'
|
|
|
64337f |
my $constants;
|
|
|
64337f |
my $multiple = ref $_[0];
|
|
|
64337f |
- my $pkg = caller;
|
|
|
64337f |
+ my $caller = caller;
|
|
|
64337f |
my $flush_mro;
|
|
|
64337f |
my $symtab;
|
|
|
64337f |
|
|
|
64337f |
if (_CAN_PCS) {
|
|
|
64337f |
no strict 'refs';
|
|
|
64337f |
- $symtab = \%{$pkg . '::'};
|
|
|
64337f |
+ $symtab = \%{$caller . '::'};
|
|
|
64337f |
};
|
|
|
64337f |
|
|
|
64337f |
if ( $multiple ) {
|
|
|
64337f |
@@ -70,6 +81,20 @@ sub import {
|
|
|
64337f |
}
|
|
|
64337f |
|
|
|
64337f |
foreach my $name ( keys %$constants ) {
|
|
|
64337f |
+ my $pkg;
|
|
|
64337f |
+ my $symtab = $symtab;
|
|
|
64337f |
+ my $orig_name = $name;
|
|
|
64337f |
+ if ($name =~ s/(.*)(?:::|')(?=.)//s) {
|
|
|
64337f |
+ $pkg = $1;
|
|
|
64337f |
+ if (_CAN_PCS && $pkg ne $caller) {
|
|
|
64337f |
+ no strict 'refs';
|
|
|
64337f |
+ $symtab = \%{$pkg . '::'};
|
|
|
64337f |
+ }
|
|
|
64337f |
+ }
|
|
|
64337f |
+ else {
|
|
|
64337f |
+ $pkg = $caller;
|
|
|
64337f |
+ }
|
|
|
64337f |
+
|
|
|
64337f |
# Normal constant name
|
|
|
64337f |
if ($name =~ $normal_constant_name and !$forbidden{$name}) {
|
|
|
64337f |
# Everything is okay
|
|
|
64337f |
@@ -117,7 +142,7 @@ sub import {
|
|
|
64337f |
my $full_name = "${pkg}::$name";
|
|
|
64337f |
$declared{$full_name}++;
|
|
|
64337f |
if ($multiple || @_ == 1) {
|
|
|
64337f |
- my $scalar = $multiple ? $constants->{$name} : $_[0];
|
|
|
64337f |
+ my $scalar = $multiple ? $constants->{$orig_name} : $_[0];
|
|
|
64337f |
|
|
|
64337f |
if (_DOWNGRADE) { # for 5.8 to 5.14
|
|
|
64337f |
# Work around perl bug #31991: Sub names (actually glob
|
|
|
64337f |
@@ -128,27 +153,50 @@ sub import {
|
|
|
64337f |
|
|
|
64337f |
# The constant serves to optimise this entire block out on
|
|
|
64337f |
# 5.8 and earlier.
|
|
|
64337f |
- if (_CAN_PCS && $symtab && !exists $symtab->{$name}) {
|
|
|
64337f |
- # No typeglob yet, so we can use a reference as space-
|
|
|
64337f |
- # efficient proxy for a constant subroutine
|
|
|
64337f |
+ if (_CAN_PCS) {
|
|
|
64337f |
+ # Use a reference as a proxy for a constant subroutine.
|
|
|
64337f |
+ # If this is not a glob yet, it saves space. If it is
|
|
|
64337f |
+ # a glob, we must still create it this way to get the
|
|
|
64337f |
+ # right internal flags set, as constants are distinct
|
|
|
64337f |
+ # from subroutines created with sub(){...}.
|
|
|
64337f |
# The check in Perl_ck_rvconst knows that inlinable
|
|
|
64337f |
# constants from cv_const_sv are read only. So we have to:
|
|
|
64337f |
Internals::SvREADONLY($scalar, 1);
|
|
|
64337f |
- $symtab->{$name} = \$scalar;
|
|
|
64337f |
- ++$flush_mro;
|
|
|
64337f |
+ if (!exists $symtab->{$name}) {
|
|
|
64337f |
+ $symtab->{$name} = \$scalar;
|
|
|
64337f |
+ ++$flush_mro->{$pkg};
|
|
|
64337f |
+ }
|
|
|
64337f |
+ else {
|
|
|
64337f |
+ local $constant::{_dummy} = \$scalar;
|
|
|
64337f |
+ *$full_name = \&{"_dummy"};
|
|
|
64337f |
+ }
|
|
|
64337f |
} else {
|
|
|
64337f |
*$full_name = sub () { $scalar };
|
|
|
64337f |
}
|
|
|
64337f |
} elsif (@_) {
|
|
|
64337f |
my @list = @_;
|
|
|
64337f |
- *$full_name = sub () { @list };
|
|
|
64337f |
+ if (_CAN_PCS_FOR_ARRAY) {
|
|
|
64337f |
+ _make_const($list[$_]) for 0..$#list;
|
|
|
64337f |
+ _make_const(@list);
|
|
|
64337f |
+ if (!exists $symtab->{$name}) {
|
|
|
64337f |
+ $symtab->{$name} = \@list;
|
|
|
64337f |
+ $flush_mro->{$pkg}++;
|
|
|
64337f |
+ }
|
|
|
64337f |
+ else {
|
|
|
64337f |
+ local $constant::{_dummy} = \@list;
|
|
|
64337f |
+ *$full_name = \&{"_dummy"};
|
|
|
64337f |
+ }
|
|
|
64337f |
+ }
|
|
|
64337f |
+ else { *$full_name = sub () { @list }; }
|
|
|
64337f |
} else {
|
|
|
64337f |
*$full_name = sub () { };
|
|
|
64337f |
}
|
|
|
64337f |
}
|
|
|
64337f |
}
|
|
|
64337f |
# Flush the cache exactly once if we make any direct symbol table changes.
|
|
|
64337f |
- mro::method_changed_in($pkg) if _CAN_PCS && $flush_mro;
|
|
|
64337f |
+ if (_CAN_PCS && $flush_mro) {
|
|
|
64337f |
+ mro::method_changed_in($_) for keys %$flush_mro;
|
|
|
64337f |
+ }
|
|
|
64337f |
}
|
|
|
64337f |
|
|
|
64337f |
1;
|
|
|
64337f |
@@ -190,7 +238,7 @@ This pragma allows you to declare consta
|
|
|
64337f |
|
|
|
64337f |
When you declare a constant such as C<PI> using the method shown
|
|
|
64337f |
above, each machine your script runs upon can have as many digits
|
|
|
64337f |
-of accuracy as it can use. Also, your program will be easier to
|
|
|
64337f |
+of accuracy as it can use. Also, your program will be easier to
|
|
|
64337f |
read, more likely to be maintained (and maintained correctly), and
|
|
|
64337f |
far less likely to send a space probe to the wrong planet because
|
|
|
64337f |
nobody noticed the one equation in which you wrote C<3.14195>.
|
|
|
64337f |
@@ -203,7 +251,7 @@ away if the constant is false.
|
|
|
64337f |
=head1 NOTES
|
|
|
64337f |
|
|
|
64337f |
As with all C<use> directives, defining a constant happens at
|
|
|
64337f |
-compile time. Thus, it's probably not correct to put a constant
|
|
|
64337f |
+compile time. Thus, it's probably not correct to put a constant
|
|
|
64337f |
declaration inside of a conditional statement (like C
|
|
|
64337f |
{ use constant ... }>).
|
|
|
64337f |
|
|
|
64337f |
@@ -221,10 +269,6 @@ point to data which may be changed, as t
|
|
|
64337f |
ARRAY->[1] = " be changed";
|
|
|
64337f |
print ARRAY->[1];
|
|
|
64337f |
|
|
|
64337f |
-Dereferencing constant references incorrectly (such as using an array
|
|
|
64337f |
-subscript on a constant hash reference, or vice versa) will be trapped at
|
|
|
64337f |
-compile time.
|
|
|
64337f |
-
|
|
|
64337f |
Constants belong to the package they are defined in. To refer to a
|
|
|
64337f |
constant defined in another package, specify the full package name, as
|
|
|
64337f |
in C<Some::Package::CONSTANT>. Constants may be exported by modules,
|
|
|
64337f |
@@ -233,11 +277,18 @@ as C<< Some::Package->CONSTANT >> or as
|
|
|
64337f |
C<$obj> is an instance of C<Some::Package>. Subclasses may define
|
|
|
64337f |
their own constants to override those in their base class.
|
|
|
64337f |
|
|
|
64337f |
+As of version 1.32 of this module, constants can be defined in packages
|
|
|
64337f |
+other than the caller, by including the package name in the name of the
|
|
|
64337f |
+constant:
|
|
|
64337f |
+
|
|
|
64337f |
+ use constant "OtherPackage::FWIBBLE" => 7865;
|
|
|
64337f |
+ constant->import("Other::FWOBBLE",$value); # dynamically at run time
|
|
|
64337f |
+
|
|
|
64337f |
The use of all caps for constant names is merely a convention,
|
|
|
64337f |
although it is recommended in order to make constants stand out
|
|
|
64337f |
and to help avoid collisions with other barewords, keywords, and
|
|
|
64337f |
-subroutine names. Constant names must begin with a letter or
|
|
|
64337f |
-underscore. Names beginning with a double underscore are reserved. Some
|
|
|
64337f |
+subroutine names. Constant names must begin with a letter or
|
|
|
64337f |
+underscore. Names beginning with a double underscore are reserved. Some
|
|
|
64337f |
poor choices for names will generate warnings, if warnings are enabled at
|
|
|
64337f |
compile time.
|
|
|
64337f |
|
|
|
64337f |
@@ -312,15 +363,15 @@ constants without any problems.
|
|
|
64337f |
=head1 TECHNICAL NOTES
|
|
|
64337f |
|
|
|
64337f |
In the current implementation, scalar constants are actually
|
|
|
64337f |
-inlinable subroutines. As of version 5.004 of Perl, the appropriate
|
|
|
64337f |
+inlinable subroutines. As of version 5.004 of Perl, the appropriate
|
|
|
64337f |
scalar constant is inserted directly in place of some subroutine
|
|
|
64337f |
-calls, thereby saving the overhead of a subroutine call. See
|
|
|
64337f |
+calls, thereby saving the overhead of a subroutine call. See
|
|
|
64337f |
L<perlsub/"Constant Functions"> for details about how and when this
|
|
|
64337f |
happens.
|
|
|
64337f |
|
|
|
64337f |
In the rare case in which you need to discover at run time whether a
|
|
|
64337f |
particular constant has been declared via this module, you may use
|
|
|
64337f |
-this function to examine the hash C<%constant::declared>. If the given
|
|
|
64337f |
+this function to examine the hash C<%constant::declared>. If the given
|
|
|
64337f |
constant name does not include a package name, the current package is
|
|
|
64337f |
used.
|
|
|
64337f |
|
|
|
64337f |
@@ -335,11 +386,12 @@ used.
|
|
|
64337f |
|
|
|
64337f |
=head1 CAVEATS
|
|
|
64337f |
|
|
|
64337f |
-In the current version of Perl, list constants are not inlined
|
|
|
64337f |
-and some symbols may be redefined without generating a warning.
|
|
|
64337f |
+List constants are not inlined unless you are using Perl v5.20 or higher.
|
|
|
64337f |
+In v5.20 or higher, they are still not read-only, but that may change in
|
|
|
64337f |
+future versions.
|
|
|
64337f |
|
|
|
64337f |
It is not possible to have a subroutine or a keyword with the same
|
|
|
64337f |
-name as a constant in the same package. This is probably a Good Thing.
|
|
|
64337f |
+name as a constant in the same package. This is probably a Good Thing.
|
|
|
64337f |
|
|
|
64337f |
A constant with a name in the list C
|
|
|
64337f |
ENV INC SIG> is not allowed anywhere but in package C<main::>, for
|
|
|
64337f |
diff -up constant-1.27/t/constant.t.127 constant-1.27/t/constant.t
|
|
|
64337f |
--- constant-1.27/t/constant.t.127 2013-03-21 01:48:49.000000000 +0100
|
|
|
64337f |
+++ constant-1.27/t/constant.t 2015-01-24 16:02:08.000000000 +0100
|
|
|
64337f |
@@ -9,7 +9,7 @@ END { @warnings && print STDERR join "\n
|
|
|
64337f |
|
|
|
64337f |
|
|
|
64337f |
use strict;
|
|
|
64337f |
-use Test::More tests => 96;
|
|
|
64337f |
+use Test::More tests => 109;
|
|
|
64337f |
my $TB = Test::More->builder;
|
|
|
64337f |
|
|
|
64337f |
BEGIN { use_ok('constant'); }
|
|
|
64337f |
@@ -122,7 +122,7 @@ print $output CCODE->($curr_test+4);
|
|
|
64337f |
$TB->current_test($curr_test+4);
|
|
|
64337f |
|
|
|
64337f |
eval q{ CCODE->{foo} };
|
|
|
64337f |
-ok scalar($@ =~ /^Constant is not a HASH/);
|
|
|
64337f |
+ok scalar($@ =~ /^Constant is not a HASH|Not a HASH reference/);
|
|
|
64337f |
|
|
|
64337f |
|
|
|
64337f |
# Allow leading underscore
|
|
|
64337f |
@@ -346,3 +346,78 @@ $kloong = 'schlozhauer';
|
|
|
64337f |
eval 'use constant undef, 5; 1';
|
|
|
64337f |
like $@, qr/\ACan't use undef as constant name at /;
|
|
|
64337f |
}
|
|
|
64337f |
+
|
|
|
64337f |
+# Constants created by "use constant" should be read-only
|
|
|
64337f |
+
|
|
|
64337f |
+# This test will not test what we are trying to test if this glob entry
|
|
|
64337f |
+# exists already, so test that, too.
|
|
|
64337f |
+ok !exists $::{immutable};
|
|
|
64337f |
+eval q{
|
|
|
64337f |
+ use constant immutable => 23987423874;
|
|
|
64337f |
+ for (immutable) { eval { $_ = 22 } }
|
|
|
64337f |
+ like $@, qr/^Modification of a read-only value attempted at /,
|
|
|
64337f |
+ 'constant created in empty stash slot is immutable';
|
|
|
64337f |
+ eval { for (immutable) { ${\$_} = 432 } };
|
|
|
64337f |
+ SKIP: {
|
|
|
64337f |
+ require Config;
|
|
|
64337f |
+ if ($Config::Config{useithreads}) {
|
|
|
64337f |
+ skip "fails under threads", 1 if $] < 5.019003;
|
|
|
64337f |
+ }
|
|
|
64337f |
+ like $@, qr/^Modification of a read-only value attempted at /,
|
|
|
64337f |
+ '... and immutable through refgen, too';
|
|
|
64337f |
+ }
|
|
|
64337f |
+};
|
|
|
64337f |
+() = \&{"immutable"}; # reify
|
|
|
64337f |
+eval 'for (immutable) { $_ = 42 }';
|
|
|
64337f |
+like $@, qr/^Modification of a read-only value attempted at /,
|
|
|
64337f |
+ '... and after reification';
|
|
|
64337f |
+
|
|
|
64337f |
+# Use an existing stash element this time.
|
|
|
64337f |
+# This next line is sufficient to trigger a different code path in
|
|
|
64337f |
+# constant.pm.
|
|
|
64337f |
+() = \%::existing_stash_entry;
|
|
|
64337f |
+use constant existing_stash_entry => 23987423874;
|
|
|
64337f |
+for (existing_stash_entry) { eval { $_ = 22 } }
|
|
|
64337f |
+like $@, qr/^Modification of a read-only value attempted at /,
|
|
|
64337f |
+ 'constant created in existing stash slot is immutable';
|
|
|
64337f |
+eval { for (existing_stash_entry) { ${\$_} = 432 } };
|
|
|
64337f |
+SKIP: {
|
|
|
64337f |
+ if ($Config::Config{useithreads}) {
|
|
|
64337f |
+ skip "fails under threads", 1 if $] < 5.019003;
|
|
|
64337f |
+ }
|
|
|
64337f |
+ like $@, qr/^Modification of a read-only value attempted at /,
|
|
|
64337f |
+ '... and immutable through refgen, too';
|
|
|
64337f |
+}
|
|
|
64337f |
+
|
|
|
64337f |
+# Test that list constants are also immutable. This only works under
|
|
|
64337f |
+# 5.19.3 and later.
|
|
|
64337f |
+SKIP: {
|
|
|
64337f |
+ skip "fails under 5.19.2 and earlier", 3 if $] < 5.019003;
|
|
|
64337f |
+ local $TODO = "disabled for now; breaks CPAN; see perl #119045";
|
|
|
64337f |
+ use constant constant_list => 1..2;
|
|
|
64337f |
+ for (constant_list) {
|
|
|
64337f |
+ my $num = $_;
|
|
|
64337f |
+ eval { $_++ };
|
|
|
64337f |
+ like $@, qr/^Modification of a read-only value attempted at /,
|
|
|
64337f |
+ "list constant has constant elements ($num)";
|
|
|
64337f |
+ }
|
|
|
64337f |
+ undef $TODO;
|
|
|
64337f |
+ # Whether values are modifiable or no, modifying them should not affect
|
|
|
64337f |
+ # future return values.
|
|
|
64337f |
+ my @values;
|
|
|
64337f |
+ for(1..2) {
|
|
|
64337f |
+ for ((constant_list)[0]) {
|
|
|
64337f |
+ push @values, $_;
|
|
|
64337f |
+ eval {$_++};
|
|
|
64337f |
+ }
|
|
|
64337f |
+ }
|
|
|
64337f |
+ is $values[1], $values[0],
|
|
|
64337f |
+ 'modifying list const elements does not affect future retavls';
|
|
|
64337f |
+}
|
|
|
64337f |
+
|
|
|
64337f |
+use constant { "tahi" => 1, "rua::rua" => 2, "toru'toru" => 3 };
|
|
|
64337f |
+use constant "wha::wha" => 4;
|
|
|
64337f |
+is tahi, 1, 'unqualified constant declared with constants in other pkgs';
|
|
|
64337f |
+is rua::rua, 2, 'constant declared with ::';
|
|
|
64337f |
+is toru::toru, 3, "constant declared with '";
|
|
|
64337f |
+is wha::wha, 4, 'constant declared by itself with ::';
|
|
|
64337f |
diff -up constant-1.27/t/utf8.t.127 constant-1.27/t/utf8.t
|