Currently it enables the // and //= operators (disabled by default).
'err' is more difficult to disable because it's a keyword. (It also causes
less backward compatibility problems.)
This pragma works correctly with lexical scopes, but doesn't propagate
into eval()ed strings (due to a known bug on %^H).
--- t/op/dor.t.orig Sun Aug 25 21:53:09 2002
+++ t/op/dor.t Tue Aug 27 22:32:13 2002
@@ -10,6 +10,8 @@
package main;
require './test.pl';
+use perl6ish 'defined-or';
+
plan( tests => 25 );
my($x);
@@ -56,6 +58,8 @@
# Test that various syntaxes are allowed
for (qw(getc pos readline readlink undef umask <> <FOO> <$foo> -f)) {
- eval "sub { $_ // 0 }";
+ # TODO it should not be necessary to repeat "use perl6ish" in the eval.
+ # This is due to %^H not propagating into eval "".
+ eval "sub { use perl6ish 'defined-or'; $_ // 0 }";
is($@, '', "$_ // ... compiles");
}
--- toke.c.orig Sun Aug 25 21:53:09 2002
+++ toke.c Tue Aug 27 22:55:54 2002
@@ -38,6 +38,8 @@ static I32 utf16rev_textfilter(pTHX_ int
#define XFAKEBRACK 128
#define XENUMMASK 127
+#define HINT_PERL6ISH_DEFINEDOR 0x00000001
+
#ifdef USE_UTF8_SCRIPTS
# define UTF (!IN_BYTES)
#else
@@ -3604,39 +3606,58 @@ Perl_yylex(pTHX)
TERM('@');
case '/': /* may be division, defined-or, or pattern */
- if (PL_expect == XTERMORDORDOR && s[1] == '/') {
- s += 2;
- AOPERATOR(DORDOR);
+ if (PL_expect == XTERMORDORDOR && s[1] == '/'
+ && (PL_hints & HINT_LOCALIZE_HH))
+ {
+ HV *table = GvHV(PL_hintgv);
+ SV **svp;
+ if (table && (svp = hv_fetch(table,"perl6ish",8,FALSE))
+ && *svp && SvOK(*svp)
+ && (SvIVX(*svp) & HINT_PERL6ISH_DEFINEDOR))
+ {
+ s += 2;
+ AOPERATOR(DORDOR);
+ }
}
case '?': /* may either be conditional or pattern */
- if(PL_expect == XOPERATOR) {
- tmp = *s++;
- if(tmp == '?') {
- OPERATOR('?');
- }
- else {
- tmp = *s++;
- if(tmp == '/') {
- /* A // operator. */
- AOPERATOR(DORDOR);
- }
- else {
- s--;
- Mop(OP_DIVIDE);
- }
- }
- }
- else {
- /* Disable warning on "study /blah/" */
- if (PL_oldoldbufptr == PL_last_uni
- && (*PL_last_uni != 's' || s - PL_last_uni < 5
- || memNE(PL_last_uni, "study", 5)
- || isALNUM_lazy_if(PL_last_uni+5,UTF)
- ))
- check_uni();
- s = scan_pat(s,OP_MATCH);
- TERM(sublex_start());
- }
+ if (PL_expect == XOPERATOR) {
+ tmp = *s++;
+ if (tmp == '?') {
+ OPERATOR('?');
+ }
+ if (PL_hints & HINT_LOCALIZE_HH) {
+ HV *table = GvHV(PL_hintgv);
+ SV **svp;
+ if (table && (svp = hv_fetch(table,"perl6ish",8,FALSE))
+ && *svp && SvOK(*svp)
+ && (SvIVX(*svp) & HINT_PERL6ISH_DEFINEDOR))
+ {
+ tmp = *s++;
+ if (tmp == '/') {
+ /* A // operator. */
+ AOPERATOR(DORDOR);
+ }
+ else {
+ s--;
+ Mop(OP_DIVIDE);
+ }
+ }
+ }
+ if (tmp == '/')
+ Mop(OP_DIVIDE);
+ OPERATOR(tmp);
+ }
+ else {
+ /* Disable warning on "study /blah/" */
+ if (PL_oldoldbufptr == PL_last_uni
+ && (*PL_last_uni != 's' || s - PL_last_uni < 5
+ || memNE(PL_last_uni, "study", 5)
+ || isALNUM_lazy_if(PL_last_uni+5,UTF)
+ ))
+ check_uni();
+ s = scan_pat(s,OP_MATCH);
+ TERM(sublex_start());
+ }
case '.':
if (PL_lex_formbrack && PL_lex_brackets == PL_lex_formbrack
--- MANIFEST.orig Tue Aug 27 21:11:38 2002
+++ MANIFEST Tue Aug 27 22:47:05 2002
@@ -1368,6 +1368,8 @@
lib/overload.pm Module for overloading perl operators
lib/overload.t See if operator overloading works
lib/perl5db.pl Perl debugging routines
+lib/perl6ish.pm Pragma to use Perl 6-like syntax
+lib/perl6ish.t See if the perl6ish pragma works
lib/PerlIO.pm PerlIO support module
lib/PerlIO/via/QuotedPrint.pm PerlIO::via::QuotedPrint
lib/PerlIO/via/t/QuotedPrint.t PerlIO::via::QuotedPrint
--- /dev/null Thu Aug 24 11:00:32 2000
+++ lib/perl6ish.pm Tue Aug 27 22:35:54 2002
@@ -0,0 +1,68 @@
+package perl6ish;
+
+use strict;
+
+our $VERSION = '0.01';
+
+our $DEFINEDOR = 0x00000001;
+our $ALL = 0x00000001;
+
+sub import {
+ shift;
+ $^H |= 0x00020000; # HINT_LOCALIZE_HH
+ if (@_ == 0 || @_ == 1 && $_[0] eq 'all') {
+ $^H{perl6ish} |= $ALL;
+ }
+ else {
+ for my $h (@_) {
+ if ($h eq 'defined-or') {
+ $^H{perl6ish} |= $DEFINEDOR;
+ }
+ }
+ }
+}
+
+sub unimport {
+ shift;
+ if (@_ == 0 || @_ == 1 && $_[0] eq 'all') {
+ $^H{perl6ish} &= ~$ALL;
+ }
+ else {
+ for my $h (@_) {
+ if ($h eq 'defined-or') {
+ $^H{perl6ish} &= ~$DEFINEDOR;
+ }
+ }
+ }
+}
+
+1;
+__END__
+
+=head1 NAME
+
+perl6ish - perl pragma to enable Perl 6-like constructs
+
+=head1 SYNOPSIS
+
+ use perl6ish; # eqv to "use perl6ish 'all';"
+
+ use perl6ish 'defined-or';
+ my $x = shift // 0;
+
+ no perl6ish 'defined-or';
+
+=head1 DESCRIPTION
+
+This pragma allows to use use in Perl 5 some Perl 6-like constructs,
+that aren't fully compatible with the legacy Perl 6 syntax.
+
+Currently only the availability of the C<//> and C<//=> operators
+is controlled by this pragma.
+
+=head1 BUGS
+
+This pragma is lexically scoped, but it currently doesn't propagate to
+eval()'ed strings.
+
+=cut
--- /dev/null Thu Aug 24 11:00:32 2000
+++ lib/perl6ish.t Tue Aug 27 22:47:39 2002
@@ -0,0 +1,23 @@
+#!./perl
+
+BEGIN {
+ chdir 't' if -d 't';
+ @INC = qw(../lib);
+ require './test.pl';
+}
+
+plan( tests => 4 );
+
+$SIG{__WARN__} = sub {}; # disable mandatory warnings
+
+# Tests "use perl6ish 'defined-or'"
+
+for (qw(0//1 shift//0 shift()//0 $x//=0)) {
+ eval qq{
+ use perl6ish 'defined-or';
+ $_;
+ no perl6ish 'defined-or';
+ $_;
+ };
+ like( $@, qr/at \(eval \d+\) line 5/, $_);
+}
End of patch.
Surely "legacy Perl 5 syntax" ?
Tony
Not with my 5.8.0 :)))
l1:/u/usr/merijn 104 > perl -le '$a = undef; $b = 2; $c = $a // $b; print $c'
2
l1:/u/usr/merijn 105 > perl -V | perl -ne '/Characteristics/../Compiled/ and print'
Characteristics of this binary (from libperl):
Compile-time options: DEBUGGING USE_LARGE_FILES
Locally applied patches:
// patches 17682, 17690, and 17777
Built under hpux
Compiled at Aug 27 2002 11:08:32
l1:/u/usr/merijn 106 >
This is a clean 5.8.0 with 17682, 17690, and 17777
So I guess your patch disables //. I still wonder *why*. It is 99.9999 %
backward compatible, so just give the user that functionality.
If you want my opinion (I know you don't) *en*able this by default.
> 'err' is more difficult to disable because it's a keyword. (It also causes
> less backward compatibility problems.)
>
> This pragma works correctly with lexical scopes, but doesn't propagate
> into eval()ed strings (due to a known bug on %^H).
--
H.Merijn Brand Amsterdam Perl Mongers (http://amsterdam.pm.org/)
using perl-5.6.1, 5.8.0 & 633 on HP-UX 10.20 & 11.00, AIX 4.2, AIX 4.3,
WinNT 4, Win2K pro & WinCE 2.11. Smoking perl CORE: smo...@perl.org
http://archives.develooper.com/daily...@perl.org/ per...@perl.org
send smoke reports to: smokers...@perl.org, QA: http://qa.perl.org
I don't have a strong opinion on this. (Except that I'd really like
to have // in my day-job!)
I remember that Hugo wondered previously about what should and shouldn't
go into an hypothetic perl6ish pragma. He wanted non-compatible stuff
to be optional. He'll decide whether // goes into this category.
I made the patch for fun, to demonstrate it was possible to change
perl's parsing at compile-time.
So do I, and I've taken a step further. The above mentioned perl is slowly
finding it's way to all our customers, and I will probably even update the
binary I made available for the HP-UX folks.
> I remember that Hugo wondered previously about what should and shouldn't
> go into an hypothetic perl6ish pragma. He wanted non-compatible stuff
> to be optional. He'll decide whether // goes into this category.
Please not. If Hugo decides so anyway, can we have something like an
environment variable that controls it? setenv PERL6ISH "//,re-null,..."
> I made the patch for fun, to demonstrate it was possible to change
> perl's parsing at compile-time.
Good.
You already have it : PERL5OPT=-Mperl6ish=defined-or
(please don't suggest envvar names that begin with PERL6 ;-)
While I am in no hurry to make a final decision on this, I am reluctant
to cause _any_ backward compatibility problems when we can so easily
avoid them by making the new syntax available on request only.
As Rafael mentions, you can use PERL5OPT to turn it on by default,
though I wouldn't recommend it unless you are very confident about
the provenance of all perl code you ever run, explicitly or implicitly.
Hugo
The pragma is lexically scoped, if you enable it via PERL5OPT it'll be
available only for the script, not for the included modules. (Or at least
this should be the case.)
Well which is it? 'cos if you move when PERL5OPT is processed
you have a chance of breaking peoples existing PERL5OPT uses.
--
Nick Ing-Simmons
http://www.ni-s.u-net.com/
Thanks. Not applied just yet.
:- if (PL_expect == XTERMORDORDOR && s[1] == '/') {
:- s += 2;
:- AOPERATOR(DORDOR);
:+ if (PL_expect == XTERMORDORDOR && s[1] == '/'
:+ && (PL_hints & HINT_LOCALIZE_HH))
:+ {
:+ HV *table = GvHV(PL_hintgv);
:+ SV **svp;
:+ if (table && (svp = hv_fetch(table,"perl6ish",8,FALSE))
:+ && *svp && SvOK(*svp)
:+ && (SvIVX(*svp) & HINT_PERL6ISH_DEFINEDOR))
:+ {
:+ s += 2;
:+ AOPERATOR(DORDOR);
:+ }
This code is getting repeated regularly; it should at least be
abstracted out. But I think we'll be slowing compilation down
a lot as we start to expand the scope of 'perl6ish' unless we
can short-circuit that test by caching it.
The hint flags should probably be moved out to a separate include
file unless we're quite sure toke.c is the only place we'll ever
need them.
I think we should also concentrate on fixing propagation of hints
rather than introducing a lot of scattered code to workaround
the lack.
Hugo