Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

misleading diagnostic for y() function call #13308

Open
p5pRT opened this issue Sep 24, 2013 · 9 comments
Open

misleading diagnostic for y() function call #13308

p5pRT opened this issue Sep 24, 2013 · 9 comments

Comments

@p5pRT
Copy link

p5pRT commented Sep 24, 2013

Migrated from rt.perl.org#119987 (status was 'open')

Searchable as RT119987$

@p5pRT
Copy link
Author

p5pRT commented Sep 24, 2013

From victor@vsespb.ru

related old ticket​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=30045
prior to 5.12 errors related to y() call have some useful error message.
but not now.

$cat 1.pl

use diagnostics;
sub y {};
y(1);

$ perlbrew exec --with perl-5.10.1 perl 1.pl
perl-5.10.1

Transliteration replacement not terminated at 1.pl line 3 (#1)
  (F) The lexer couldn't find the final delimiter of a tr///, tr[][],
  y/// or y[][] construct.

Uncaught exception from user code​:
  Transliteration replacement not terminated at 1.pl line 3.
at 1.pl line 3

$ perlbrew exec --with perl-5.19.4 perl 1.pl
perl-5.19.4

syntax error at 1.pl line 4, at EOF
  (Might be a runaway multi-line ;; string starting on line 3)
Execution of 1.pl aborted due to compilation errors (#1)
  (F) Probably means you had a syntax error. Common reasons include​:

  A keyword is misspelled.
  A semicolon is missing.
  A comma is missing.
  An opening or closing parenthesis is missing.
  An opening or closing brace is missing.
  A closing quote is missing.

  Often there will be another error message associated with the syntax
  error giving more information. (Sometimes it helps to turn on -w.)
  The error message itself often tells you where it was in the line when
  it decided to give up. Sometimes the actual error is several tokens
  before this, because Perl is good at understanding random input.
  Occasionally the line number may be misleading, and once in a blue moon
  the only way to figure out what's triggering the error is to call
  perl -c repeatedly, chopping away half the program each time to see
  if the error went away. Sort of the cybernetic version of 20 questions.

Uncaught exception from user code​:
  syntax error at 1.pl line 4, at EOF
  (Might be a runaway multi-line ;; string starting on line 3)
  Execution of 1.pl aborted due to compilation errors.

@p5pRT
Copy link
Author

p5pRT commented Sep 25, 2013

From @nwc10

On Tue, Sep 24, 2013 at 12​:20​:40PM -0700, Victor Efimov wrote​:

# New Ticket Created by Victor Efimov
# Please include the string​: [perl #119987]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=119987 >

related old ticket​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=30045
prior to 5.12 errors related to y() call have some useful error message.
but not now.

$cat 1.pl

use diagnostics;
sub y {};
y(1);

$ perlbrew exec --with perl-5.10.1 perl 1.pl
perl-5.10.1

Transliteration replacement not terminated at 1.pl line 3 (#1)
(F) The lexer couldn't find the final delimiter of a tr///, tr[][],
y/// or y[][] construct.

Uncaught exception from user code​:
Transliteration replacement not terminated at 1.pl line 3.
at 1.pl line 3

$ perlbrew exec --with perl-5.19.4 perl 1.pl
perl-5.19.4

syntax error at 1.pl line 4, at EOF
(Might be a runaway multi-line ;; string starting on line 3)
Execution of 1.pl aborted due to compilation errors (#1)

That ';' at the end of the last line appears to be crucial. If I remove it,
even on blead I see the useful diagnostic​:

$ ./perl -e 'sub y {};' -e 'y(1)'
Transliteration replacement not terminated at -e line 2.

Bisecting the example as an eval

bisect.pl --target=miniperl -e 'sub y {}; eval "y(1);"; print "$]​: $@​"; exit 1 unless $@​ =~ /Transliteration/'

reveals that the message changes with this commit (which is post 5.12.0)​:

commit 1107659
Author​: Father Chrysostomos <sprout@​cpan.org>
Date​: Mon Aug 27 18​:26​:11 2012 -0700

  Fix eval 'q;;'

  The parser expects a semicolon at the end of every statement, so the
  lexer provides one. It was not doing so for evals ending with a
  semicolon, even if that semicolon was not a statement-terminating
  semicolon.

Putting the example into a file reveals the earlier commit which changed
behaviour​:

$ cat ../test/119987.pl
sub y {};
y(1);
$ bisect.pl --target miniperl -- sh -c './miniperl -Ilib ../test/119987.pl 2>&1 | grep Transliteration'

commit f0e67a1
Author​: Zefram <zefram@​fysh.org>
Date​: Sun Nov 15 14​:25​:50 2009 +0100

  lexer API

  Attached is a patch that adds a public API for the lowest layers of
  lexing. This is meant to provide a solid foundation for the parsing that
  Devel​::Declare and similar modules do, and it complements the pluggable
  keyword mechanism. The API consists of some existing variables combined
  with some new functions, all marked as experimental (which making them
  public certainly is).

:100644 100644 22db6a3c9011829aff5176a7bacd4373f9c1d354 b8073eb771a2c615c876970bc1883bd4316cc88c M MANIFEST
:100644 100644 7522055a288adf11291c654a30726bd618c11f25 f17f7ada0a8c023af12e8aa9b7800f9ccf643df5 M embed.fnc
:100644 100644 52e40c6fa2f68c4c009a83d7669522543a9baad1 17bf11a5139254f0a5f6a46473bb136d1c145259 M embed.h
:040000 040000 23226494a6184590278d718527f383b69fff2cf3 6ebec696e22c1a6f7b1b4043db5a090006e9f1b1 M ext
:100644 100644 6000af755912fcd939cbe94d4662c54dd42acd5b 6a44049c4e4262b09ae4c5a0d2fd2d9749f12189 M global.sym
:100644 100644 74d8ef2197b15a99ce10a233a2f829c286043022 462dcfdef806826927c7e9c5261e46e57033960c M parser.h
:100644 100644 3639bd6ac0f26afd8537e3e9722382c2ba5beea2 3d378917c94e26aa9a550c181fdd824d6aad2e60 M perlvars.h
:040000 040000 79cfd550ba3c1ee290da3a30115bcade3d31effb 4de6df320a87c92b6db4c4df6a5b3cbace2d96bb M pod
:100644 100644 f1ab3d022e76840708a2367ea74a652b299bd6f1 fd2eb36cd42cecae815240f00f301038d0aba9fc M proto.h
:100644 100644 b8abbd854f001057679312ed03b534e0853cf490 6793f7b8669efb9df31731d9eff7507d6672c9b6 M toke.c
bisect run success
That took 610 seconds

I have no more insight than this. It may not be an easy thing to fix.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Sep 25, 2013

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Sep 25, 2013

From @ikegami

On Tue, Sep 24, 2013 at 3​:20 PM, Victor Efimov <perlbug-followup@​perl.org>wrote​:

# New Ticket Created by Victor Efimov
# Please include the string​: [perl #119987]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=119987 >

related old ticket​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=30045
prior to 5.12 errors related to y() call have some useful error message.
but not now.

$cat 1.pl

use diagnostics;
sub y {};
y(1);

$ perlbrew exec --with perl-5.10.1 perl 1.pl
perl-5.10.1

Transliteration replacement not terminated at 1.pl line 3 (#1)
(F) The lexer couldn't find the final delimiter of a tr///, tr[][],
y/// or y[][] construct.

Uncaught exception from user code​:
Transliteration replacement not terminated at 1.pl line 3.
at 1.pl line 3

$ perlbrew exec --with perl-5.19.4 perl 1.pl
perl-5.19.4

syntax error at 1.pl line 4, at EOF
(Might be a runaway multi-line ;; string starting on line 3)
Execution of 1.pl aborted due to compilation errors (#1)
(F) Probably means you had a syntax error. Common reasons include​:

    A keyword is misspelled\.
    A semicolon is missing\.
    A comma is missing\.
    An opening or closing parenthesis is missing\.
    An opening or closing brace is missing\.
    A closing quote is missing\.

Often there will be another error message associated with the syntax
error giving more information\.  \(Sometimes it helps to turn on \-w\.\)
The error message itself often tells you where it was in the line when
it decided to give up\.  Sometimes the actual error is several tokens
before this\, because Perl is good at understanding random input\.
Occasionally the line number may be misleading\, and once in a blue moon
the only way to figure out what's triggering the error is to call
perl \-c repeatedly\, chopping away half the program each time to see
if the error went away\.  Sort of the cybernetic version of 20

questions.

Uncaught exception from user code​:
syntax error at 1.pl line 4, at EOF
(Might be a runaway multi-line ;; string starting on line 3)
Execution of 1.pl aborted due to compilation errors.

The Perl parser requires a ";" at the end of the file, so it injects one,
so Perl sees.

y();
;

which is another way or writing

y()(
)

Perl doesn't emit "transliteration replacement not terminated" because it
believes the transliteration is completed (by the injected ";"). Perl emits
the syntax error because it expects a ";" to end the y/// statement, and
there isn't.

It might be possible to give a better diagnostic in the case where C<< y();

is found at the end of the file, but what about everywhere else?

perl -wE"y(1234); x(); z();"
Bareword found where operator expected at -e line 1, near "y(1234); x(); z"
syntax error at -e line 1, near "y(1234); x(); z"
Execution of -e aborted due to compilation errors.

- Eric

@p5pRT
Copy link
Author

p5pRT commented Sep 25, 2013

From victor@vsespb.ru

This example does not call sub s(). Silently.

use strict;
use warnings;
sub s { print @​_ };
sub z {};
local $_=1;
s(1);
z();

maybe it's possible to emit warnings each time when first delimiter pair
is "(" and ")" and second is ";" and ";". it's probably unusual
combination in real code.

On Wed Sep 25 08​:47​:23 2013, ikegami@​adaelis.com wrote​:

On Tue, Sep 24, 2013 at 3​:20 PM, Victor Efimov <perlbug-
followup@​perl.org>wrote​:

# New Ticket Created by Victor Efimov
# Please include the string​: [perl #119987]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=119987 >

related old ticket​:
https://rt-archive.perl.org/perl5/Ticket/Display.html?id=30045
prior to 5.12 errors related to y() call have some useful error
message.
but not now.

$cat 1.pl

use diagnostics;
sub y {};
y(1);

$ perlbrew exec --with perl-5.10.1 perl 1.pl
perl-5.10.1

Transliteration replacement not terminated at 1.pl line 3 (#1)
(F) The lexer couldn't find the final delimiter of a tr///,
tr[][],
y/// or y[][] construct.

Uncaught exception from user code​:
Transliteration replacement not terminated at 1.pl line 3.
at 1.pl line 3

$ perlbrew exec --with perl-5.19.4 perl 1.pl
perl-5.19.4

syntax error at 1.pl line 4, at EOF
(Might be a runaway multi-line ;; string starting on line 3)
Execution of 1.pl aborted due to compilation errors (#1)
(F) Probably means you had a syntax error. Common reasons
include​:

    A keyword is misspelled\.
    A semicolon is missing\.
    A comma is missing\.
    An opening or closing parenthesis is missing\.
    An opening or closing brace is missing\.
    A closing quote is missing\.

Often there will be another error message associated with the

syntax

error giving more information\.  \(Sometimes it helps to turn on

-w.)

The error message itself often tells you where it was in the

line when

it decided to give up\.  Sometimes the actual error is several

tokens

before this\, because Perl is good at understanding random input\.
Occasionally the line number may be misleading\, and once in a

blue moon

the only way to figure out what's triggering the error is to

call

perl \-c repeatedly\, chopping away half the program each time to

see

if the error went away\.  Sort of the cybernetic version of 20

questions.

Uncaught exception from user code​:
syntax error at 1.pl line 4, at EOF
(Might be a runaway multi-line ;; string starting on line
3)
Execution of 1.pl aborted due to compilation errors.

The Perl parser requires a ";" at the end of the file, so it injects
one,
so Perl sees.

y();
;

which is another way or writing

y()(
)

Perl doesn't emit "transliteration replacement not terminated" because
it
believes the transliteration is completed (by the injected ";"). Perl
emits
the syntax error because it expects a ";" to end the y/// statement,
and
there isn't.

It might be possible to give a better diagnostic in the case where C<<
y();

is found at the end of the file, but what about everywhere else?

perl -wE"y(1234); x(); z();"
Bareword found where operator expected at -e line 1, near "y(1234);
x(); z"
syntax error at -e line 1, near "y(1234); x(); z"
Execution of -e aborted due to compilation errors.

- Eric

@p5pRT
Copy link
Author

p5pRT commented Sep 27, 2013

From @rjbs

* Eric Brine <ikegami@​adaelis.com> [2013-09-25T11​:46​:33]

The Perl parser requires a ";" at the end of the file, so it injects one,
so Perl sees.

y();
;

which is another way or writing

y()(
)

*facepalm* -- *high five*

--
rjbs

@p5pRT
Copy link
Author

p5pRT commented Sep 28, 2013

From @cpansprout

On Wed Sep 25 08​:47​:23 2013, ikegami@​adaelis.com wrote​:

The Perl parser requires a ";" at the end of the file, so it injects
one,
so Perl sees.

y();
;

which is another way or writing

y()(
)

We really should change the lexer to emit the ';' itself, instead of
lying to itself about what is in the source code it is parsing.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Sep 29, 2013

From victor@vsespb.ru

On Wed Sep 25 08​:59​:08 2013, vsespb wrote​:

This example does not call sub s(). Silently.

use strict;
use warnings;
sub s { print @​_ };
sub z {};
local $_=1;
s(1);
z();

maybe it's possible to emit warnings each time when first delimiter pair
is "(" and ")" and second is ";" and ";". it's probably unusual
combination in real code.

Well, this probably half-measure.
But why there are no attempt to warn user when he tries to
declare/call/import/export subroutines with names like "s", "y", "qw",
"qq", "foreach" and anything other listed in perlfunc?

@p5pRT
Copy link
Author

p5pRT commented Sep 29, 2013

From victor@vsespb.ru

sometimes perl emits useful warnings​:

use strict;
use warnings;
sub endgrent { print "A"; }
endgrent();
__END__
Ambiguous call resolved as CORE​::endgrent(), qualify as such or use & at
H1.pl line 4.

but sometimes - no​:

use strict;
use warnings;
sub qw { print "A"; }
qw();
print "done\n";
__END__
done

use strict;
use warnings;
sub do { print "A"; }
do(1);
print "done\n";
__END__
done

use strict;
use warnings;
sub require { print "A"; }
require(1);
print "done\n";
__END__
done

On Sun Sep 29 09​:15​:35 2013, vsespb wrote​:

On Wed Sep 25 08​:59​:08 2013, vsespb wrote​:

This example does not call sub s(). Silently.

use strict;
use warnings;
sub s { print @​_ };
sub z {};
local $_=1;
s(1);
z();

maybe it's possible to emit warnings each time when first delimiter pair
is "(" and ")" and second is ";" and ";". it's probably unusual
combination in real code.

Well, this probably half-measure.
But why there are no attempt to warn user when he tries to
declare/call/import/export subroutines with names like "s", "y", "qw",
"qq", "foreach" and anything other listed in perlfunc?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants