This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #119973] Treat initial { in format args as block
authorFather Chrysostomos <sprout@cpan.org>
Sun, 19 Jan 2014 01:58:52 +0000 (17:58 -0800)
committerFather Chrysostomos <sprout@cpan.org>
Sun, 19 Jan 2014 03:11:58 +0000 (19:11 -0800)
Commit 705fe0e5f8a inadvertently caused the hash-vs-block disambigua-
tion to apply at the beginning of a format argument line.  This commit
restores the implicit ‘do’, but only when the opening brace is the
first token on that line, not embedded within an expression.

In other words, this now has a block as before:

format =
{ foo => "bar" }
.

but this still produces a hash (in 5.16 it was a block):

format =
+{ foo => "bar }
.

t/op/write.t
toke.c

index 0bad2e4..7591cde 100644 (file)
@@ -101,7 +101,7 @@ my $bas_tests = 21;
 my $bug_tests = 66 + 3 * 3 * 5 * 2 * 3 + 2 + 66 + 4 + 2 + 3 + 96 + 11;
 
 # number of tests in section 4
-my $hmb_tests = 35;
+my $hmb_tests = 37;
 
 my $tests = $bas_tests + $num_tests + $bug_tests + $hmb_tests;
 
@@ -1894,6 +1894,25 @@ write HASH;
 close HASH or die "Could not close: $!";
 is cat('Op_write.tmp'), "3\n", 'anonymous hashes';
 
+open(HASH2, '>Op_write.tmp') || die "Can't create Op_write.tmp";
+format HASH2 =
+@<<<
++{foo=>"bar"}
+.
+write HASH2;
+close HASH2 or die "Could not close: $!";
+is cat('Op_write.tmp'), "HASH\n", '+{...} is interpreted as anon hash';
+
+# Anonymous hashes
+open(BLOCK, '>Op_write.tmp') || die "Can't create Op_write.tmp";
+format BLOCK =
+@<<< @<<<
+{foo=>"bar"} # this is a block, not a hash!
+.
+write BLOCK;
+close BLOCK or die "Could not close: $!";
+is cat('Op_write.tmp'), "foo  bar\n", 'initial { is always BLOCK';
+
 # pragmata inside argument line
 open(STRICT, '>Op_write.tmp') || die "Can't create Op_write.tmp";
 format STRICT =
diff --git a/toke.c b/toke.c
index f8ebf53..290af07 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -11454,6 +11454,16 @@ S_scan_formline(pTHX_ char *s)
     if (SvCUR(stuff)) {
        PL_expect = XSTATE;
        if (needargs) {
+           const char *s2 = s;
+           while (*s2 == '\r' || *s2 == ' ' || *s2 == '\t' || *s2 == '\f'
+               || *s2 == 013)
+               s2++;
+           if (*s2 == '{') {
+               start_force(PL_curforce);
+               PL_expect = XTERMBLOCK;
+               NEXTVAL_NEXTTOKE.ival = 0;
+               force_next(DO);
+           }
            start_force(PL_curforce);
            NEXTVAL_NEXTTOKE.ival = 0;
            force_next(FORMLBRACK);