[Pugs] A couple of string interpolation edge cases

7 views
Skip to first unread message

Andrew Savige

unread,
Mar 25, 2005, 11:32:18 PM3/25/05
to perl6-c...@perl.org
I stumbled across a couple of interesting quote interpolation
edge cases:

Case 1
------

# cat ttt.p6
my $x = "{";

# pugs ttt.p6

unexpected end of input
expecting "\"", "$!", "$/", "\\" or block
NonTerm SourcePos "ttt.p6" 2 1

Is this a bug?

Case 2
------

# cat q1.pl
my $x = "$";
print "x='$x'\n";

# perl -w q1.pl
Final $ should be \$ or $name at q1.pl line 1, within string
syntax error at q1.pl line 1, near "= "$""
Execution of q1.pl aborted due to compilation errors.

# pugs q1.pl
x='$'

Wow, is pugs better than p5 here? ;-)

/-\


Find local movie times and trailers on Yahoo! Movies.
http://au.movies.yahoo.com

Luke Palmer

unread,
Mar 26, 2005, 1:14:22 AM3/26/05
to Andrew Savige, perl6-c...@perl.org
Andrew Savige writes:
> I stumbled across a couple of interesting quote interpolation
> edge cases:
>
> Case 1
> ------
>
> # cat ttt.p6
> my $x = "{";
>
> # pugs ttt.p6
>
> unexpected end of input
> expecting "\"", "$!", "$/", "\\" or block
> NonTerm SourcePos "ttt.p6" 2 1
>
> Is this a bug?

No. Braces in strings are interpolator markers:

say "The output of foo is { foo() }";

> Case 2
> ------
>
> # cat q1.pl
> my $x = "$";
> print "x='$x'\n";
>
> # perl -w q1.pl
> Final $ should be \$ or $name at q1.pl line 1, within string
> syntax error at q1.pl line 1, near "= "$""
> Execution of q1.pl aborted due to compilation errors.
>
> # pugs q1.pl
> x='$'

Hmm, given that we require no whitespace between the $ and the
identifier now, we might treat a $ not followed by \w or / as literal.

Luke

Autrijus Tang

unread,
Mar 26, 2005, 1:11:29 AM3/26/05
to perl6-c...@perl.org
On Fri, Mar 25, 2005 at 10:03:45PM -0800, Larry Wall wrote:
> Hmm, well, if it got that far. Given strict being on by default,
> this particular example should probably just die on the fact that $"
> isn't declared, since there's no $" in Perl 6.

Is $" okay as a variable name? Is everything from perlvar.pod legal? :)

my $" = 3;

Pugs parses that because it only considers $! and $/ as legal
symbolic variable names.

Thanks,
/Autrijus/

Larry Wall

unread,
Mar 26, 2005, 1:03:45 AM3/26/05
to perl6-c...@perl.org
On Sat, Mar 26, 2005 at 03:32:18PM +1100, Andrew Savige wrote:
: I stumbled across a couple of interesting quote interpolation

: edge cases:
:
: Case 1
: ------
:
: # cat ttt.p6
: my $x = "{";
:
: # pugs ttt.p6
:
: unexpected end of input
: expecting "\"", "$!", "$/", "\\" or block
: NonTerm SourcePos "ttt.p6" 2 1
:
: Is this a bug?

No, but it could probably use a better error message about a possible
runaway closure in the string, much as Perl 5 warns about runaway
strings.

: Case 2


: ------
:
: # cat q1.pl
: my $x = "$";
: print "x='$x'\n";
:
: # perl -w q1.pl
: Final $ should be \$ or $name at q1.pl line 1, within string
: syntax error at q1.pl line 1, near "= "$""
: Execution of q1.pl aborted due to compilation errors.
:
: # pugs q1.pl
: x='$'
:
: Wow, is pugs better than p5 here? ;-)

Well, yes, actually. Perl 5 manages to catch the error only because
it does bogus terminator-parsing lookahead. Pugs ought to have got a
syntax error on the backslash, I think, and reported a runaway quote
as the likely cause.

Though in fact, with a backtracking parser you should be able to
determine the point at which a different decision would have produced
a successful parse. We shouldn't generate code from the successful
parse once we're in error state, but it could give us much better
diagnostics in certain cases if we install backtracking decision points
for things that look suspiciously like they meant something else.
In this particular case the parser could have intuited exactly what
went wrong.

Hmm, well, if it got that far. Given strict being on by default,
this particular example should probably just die on the fact that $"
isn't declared, since there's no $" in Perl 6.

Larry

Larry Wall

unread,
Mar 26, 2005, 3:27:24 AM3/26/05
to perl6-c...@perl.org, perl6-l...@perl.org
On Sat, Mar 26, 2005 at 02:11:29PM +0800, Autrijus Tang wrote:

: On Fri, Mar 25, 2005 at 10:03:45PM -0800, Larry Wall wrote:
: > Hmm, well, if it got that far. Given strict being on by default,
: > this particular example should probably just die on the fact that $"
: > isn't declared, since there's no $" in Perl 6.
:
: Is $" okay as a variable name? Is everything from perlvar.pod legal? :)

Considering nobody's written perlvar.pod for Perl 6 yet, yeah, everything
in that pod is legal. :-)

: my $" = 3;


:
: Pugs parses that because it only considers $! and $/ as legal
: symbolic variable names.

$! will be a legal variable name. $/ is going away, as is $", which
means they fail under "use strict", but they'd still autocreate
globals under laxity as Perl 5 does. (I know Perl 5 exempted all
special variables from strict, but I don't see why we have to do
that for Perl 6. Merely having $_ in the lexical scope or $*! in the
global scope should be sufficient declaration to get around strict.
Though perhaps we can exempt people from having to write $*! under
strict. In fact, that probably goes for all predeclared $* names,
so $IN is legal for $*IN as long as you don't have "my $IN" hiding
it. Another way to look at it is that * variables are basically
autodeclared "our" implicitly in the outermost lexical scope.)

Sigh, I'd better rough it all in here, even if I don't have time to
do a good job on it. Maybe somebody can beat this into a real S28 pod.

$? and $@ are gone, merged in with $!. (Frees up ? twigil for $?FOO
syntax.) $^E is merged too. $! is an object with as much info as
you'd like on the current exception (unthrown outside of CATCH, thrown
inside). Unthrown exceptions are typically interesting values of undef.

$$ is now $*PID. ($$foo is now unambuous.)

$0 is gone in favor of $*PROGRAM_NAME or some such.

Anything that varied with the selected output filehandle like $|
is now a method on that filehande, and the variables don't exist.
(The p5-to-p6 translator will probably end up depending on some
$Perl5ish::selected_output_filehandle variable to emulate Perl 5's
single-arg select().) Likewise $/ and $. should be attached to
a particular input filehandle. (In fact, $/ is now the result of
the last regular expression match, though we might keep the idea of
$. around in some form or other just because it's awfully handy for
error messages. But the localizing $. business is yucky. We have
to clean that up.)

All the special format variables ($%, $=, $-, $:, $~, $^, $^A, $^L)
are gone. (Frees up the = twigil for %= POD doc structures and
old __DATA__ stream, the : twigil for private attributes, and the ~
twigil for autodeclared parameters.)

$`, $', and $+ don't exist any more, but you can dig that info out
of $/'s structures. Shortcuts into $/ include $1, $2, and such, and
the newfangled $<foo> things. Also, $& is changed to $0 for the whole
matched string. $` and $' may be $<pre> and $<post>, but you probably
have to explicitly match <pre> and <post> to get them remembered,
so we don't have a repeat of the Perl 5 sawampersand fiasco. <pre>
and <post> would automatically exclude themselves from $0. Or you
need some special flag to remember them, maybe.

%+ and %- are gone. $0, $1, $2, etc. are all objects that know
where they .start and .end. (Mind you, those methods return magical
positions that are Unicode level independent.)

$* and $# have been deprecated half of forever and are gone. $[
is a fossil that I suppose could turn into an evil pragma, if we
try to translate it at all. (Frees up * twigil for $*FOO syntax.)

$(, $), $<, and $> should all change to various $*FOO names. $] is either
something in $* or a trait of the Perl namespace. Likewise $^V, if
they aren't in fact merged.

${...} is reserved for hard refs only now. ($::(...) must be used
for symbolics refs.) ${^foo} should just change to $*foo or $*_foo
or some such.

$; is gone because the multidim hash hack is gone. $" is gone,
replaced by @foo.join(":") or some such. Likewise for $, in print
statements.

We never did find a use for $}, thank goodness.

And we still are keeping $_ around, though it's lexically scoped.

Let's see, what other damage can we do to perlvar. $a and $b are
no longer special. No bareword filehandles. $*IN, $*OUT, $*ERR.
Args come in @*ARGS rather than @ARGV. (Environment still in %ENV,
will wonders never cease.) I don't know whether @INC and %INC will
make as much sense when we're looking installed modules in a database,
though I suppose you still have to let the user add places to look.

%SIG is now %*SIG. The __DIE__ and __WARN__ hooks should be brought
out as separate &*ON_DIE and &*ON_WARN variables--they really
have nothing to do with signals. I suppose we could even do away
with %SIG and replace it with &*ON_SIGINT and such, though then we'd
lose a bit of signal introspection which would have to be provided
some other way. Oh, and we probably ought to split out &?ON_PARSEERROR
from $*ON_DIE to get rid of the $^S fiasco of Perl 5.

$^C, $^D, $^F, $^I, $^M, $^O, $^P, $^S, $^T, $^V, $^X are all renamed
to something $*FOOish, at least the ones that aren't going away entirely.

$^W is is too blunt an instrument even in Perl 5, so it's probably gone.

I'm not quite sure what to do with $^N or $^R yet. Most likely they
end up as something $<foo>ish, if they stay.

You weren't ever supposed to know about $^H and %^H. Or %{^FNORD}...

Other things might show up as global variables in support of
command-line options, like $*ARGVOUT or @*F. Some of the special
variables we've blissfull relegated to the trash heap might
creep back in as global variables that just happen to know about
$*Perl5ish::current_selected_filehandle and such, but we should
probably try to keep them as lvalue subs in &Perl5ish::ors() and such.

Anyway, it's all negotiable, except for the parts that aren't.

Larry

Andrew Savige

unread,
Mar 26, 2005, 4:06:29 AM3/26/05
to Luke Palmer, perl6-c...@perl.org
--- Luke Palmer wrote:

> Andrew Savige writes:
> > I stumbled across a couple of interesting quote interpolation
> > edge cases:

Just toppled over the edge of another two sand traps.

Case 3
------

# cat q7.p6
my $x = '\\x';
print "x='$x'\n";

# perl -w q7.p6
x='\x'

# pugs q7.p6
x='\\x'

Case 4
------

# cat q8.p6
my $x = '\\';
print "x='$x'\n";

# perl -w q8.p6
x='\'

# pugs q8.p6

unexpected "'"
expecting word character, "::", term postfix, operator, postfix conditional,
postfix loop, postfix i
teration, ";" or end of input
NonTerm SourcePos "q8.p6" 2 13

Luke Palmer

unread,
Mar 26, 2005, 5:37:41 AM3/26/05
to perl6-c...@perl.org, perl6-l...@perl.org
Larry Wall creates Sish28:

> On Sat, Mar 26, 2005 at 02:11:29PM +0800, Autrijus Tang wrote:
> : On Fri, Mar 25, 2005 at 10:03:45PM -0800, Larry Wall wrote:
> : > Hmm, well, if it got that far. Given strict being on by default,
> : > this particular example should probably just die on the fact that $"
> : > isn't declared, since there's no $" in Perl 6.
> :
> : Is $" okay as a variable name? Is everything from perlvar.pod legal? :)
>
> Considering nobody's written perlvar.pod for Perl 6 yet, yeah, everything
> in that pod is legal. :-)
>
> : my $" = 3;
> :
> : Pugs parses that because it only considers $! and $/ as legal
> : symbolic variable names.
>
> $! will be a legal variable name. $/ is going away,

By which you mean that $/ is turning into a special $0.

> Anything that varied with the selected output filehandle like $|
> is now a method on that filehande, and the variables don't exist.
> (The p5-to-p6 translator will probably end up depending on some
> $Perl5ish::selected_output_filehandle variable to emulate Perl 5's
> single-arg select().)

I think $| et al. could just translate to methods on $*OUT, and select
would look like this:

sub perl5_select($fh) {
$*OUT = $fh;
}

Is there some subtlety that that doesn't cover?

> %+ and %- are gone. $0, $1, $2, etc. are all objects that know
> where they .start and .end. (Mind you, those methods return magical
> positions that are Unicode level independent.)

Uh, it might be a bad idea to make $# objects. It might not, but it
might. I think it would be fine if they turned into regular strings
upon assignment (and to pass their full objecthood around, you'd have to
backwhack them). But the problem with keeping them objects is that if
you put them somewhere else and change them, they turn back into regular
strings without .start and .end, which may be a hard-to-track-down bug
if you're thinking that they stay objects... haven't really thought
about this much (and my head is irritatingly foggy at the moment).

> $; is gone because the multidim hash hack is gone.

Funny, I never used the multidim hash hack, I just emulated it:

$hash{"$foo$;$bar"} = $value;

> We never did find a use for $}, thank goodness.

Isn't that the "enable all of Damian's unpublished modules" variable?

> $^W is is too blunt an instrument even in Perl 5, so it's probably gone.

Well, almost. When writing a recent module, I found that one of the
modules I was using was spitting out an error from its own internal code
on one of my calls, and there was nothing wrong with the call. I
submitted a bug report to the author, and searched for a way to shut it
up so my users wouldn't complain at me. It ended up having to use $^W
at compile time (and it looks very hackish). We ought to have a
(perhaps not quite as hackish) ability to say "there's no reason for
that warning, but I can't modify your code, so just be quiet".

> I'm not quite sure what to do with $^N or $^R yet. Most likely they
> end up as something $<foo>ish, if they stay.

For $^N, how about $/[-1]?

Luke

Larry Wall

unread,
Mar 26, 2005, 3:29:37 PM3/26/05
to perl6-c...@perl.org, perl6-l...@perl.org
On Sat, Mar 26, 2005 at 03:37:41AM -0700, Luke Palmer wrote:
: > $! will be a legal variable name. $/ is going away,
:
: By which you mean that $/ is turning into a special $0.

I'd say that $0 is a specialization of $/, but yes, basically, they
both represent the current match result, albeit differently. $0 is
explicitly what would have been returned by $1 if you'd put parens
around the entire match, which is not quite the same as the complete match.
result.

: > Anything that varied with the selected output filehandle like $|


: > is now a method on that filehande, and the variables don't exist.
: > (The p5-to-p6 translator will probably end up depending on some
: > $Perl5ish::selected_output_filehandle variable to emulate Perl 5's
: > single-arg select().)
:
: I think $| et al. could just translate to methods on $*OUT, and select
: would look like this:
:
: sub perl5_select($fh) {
: $*OUT = $fh;
: }
:
: Is there some subtlety that that doesn't cover?

Like, it renders standard output nameless? In Perl 5, the selected output
handle is a level of indirection above the standard names for the streams
attached to fd 0, 1, and 2. Saying select(FH) doesn't change the meaning
of STDOUT.

: > %+ and %- are gone. $0, $1, $2, etc. are all objects that know


: > where they .start and .end. (Mind you, those methods return magical
: > positions that are Unicode level independent.)
:
: Uh, it might be a bad idea to make $# objects. It might not, but it
: might. I think it would be fine if they turned into regular strings
: upon assignment (and to pass their full objecthood around, you'd have to
: backwhack them). But the problem with keeping them objects is that if
: you put them somewhere else and change them, they turn back into regular
: strings without .start and .end, which may be a hard-to-track-down bug
: if you're thinking that they stay objects... haven't really thought
: about this much (and my head is irritatingly foggy at the moment).

My head is always irritatingly foggy. :-)

Anyway, I'm think of them more as COW objects, and they'd have to know
if their original string was yanked out from under them in any case, so
that's probably the correct moment to invalidate .start and .end, if
we even bother.

: > $; is gone because the multidim hash hack is gone.


:
: Funny, I never used the multidim hash hack, I just emulated it:
:
: $hash{"$foo$;$bar"} = $value;

Well, guess how we'll emulate it in Perl 6. :-)

: > We never did find a use for $}, thank goodness.


:
: Isn't that the "enable all of Damian's unpublished modules" variable?

Shh. Impressionable people are listening.

: > $^W is is too blunt an instrument even in Perl 5, so it's probably gone.


:
: Well, almost. When writing a recent module, I found that one of the
: modules I was using was spitting out an error from its own internal code
: on one of my calls, and there was nothing wrong with the call. I
: submitted a bug report to the author, and searched for a way to shut it
: up so my users wouldn't complain at me. It ended up having to use $^W
: at compile time (and it looks very hackish). We ought to have a
: (perhaps not quite as hackish) ability to say "there's no reason for
: that warning, but I can't modify your code, so just be quiet".

Yes, we need to be able to suppress warnings in dynamic scopes as well
as lexical, but that's probably not a scalar proposition anymore, unless
the replacement for $^W is taken as a pointer to a hash of potential
warnings. Presumably you could temporize the whole hash to suppress
all warnings, or individual elements to suppress individual warnings.
But maybe that's a good place for temporized methods instead, and then
we could name sets of warnings. Or maybe there's yet some other approach
that makes more sense. We want to encourage people to suppress only
the exact warnings they want to suppress, and not just cudgel other
modules into silence.

: > I'm not quite sure what to do with $^N or $^R yet. Most likely they


: > end up as something $<foo>ish, if they stay.
:
: For $^N, how about $/[-1]?

I guess that makes some sense. I was thinking of $/[-$n] as relative
to the current match position, but hadn't thought it through to the
point of deciding how to count those. $^N mandates counting based on
right parentheses rather than left, which I guess makes sense. So
let's say that $/[-2] means (one) rather the incomplete ((three)two):

/(one)((three) { $/[-2] } two)

I note that this is another difference between $/ and $0, since $/
is representing the current state of the match, while $0 isn't bound
till the match succeeds (unless you explicitly bind it earlier, which
is yet another difference between $0 and $/, since you can't bind $/
to mean a portion of itself).

Larry

Reply all
Reply to author
Forward
0 new messages