Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

lexical lookup and OUTER::

4 views
Skip to first unread message

Jerry Gay

unread,
Jun 23, 2006, 11:27:04 AM6/23/06
to p6i
audreyt++ pointed out on #parrot that there doesn't seem to be a way
to specify where to start finding lexicals, in support of perl's
OUTER::. eg. (from S04):

my $x = $OUTER::x;

or

my $x = OUTER::<$x>;

i propose this should be specified using a three-arg form of find_lex
<find_lex_p_s_i> where the third parameter is an integer specifying
which level in the lexical chain to start the lookup.

i've entered this TODO test in t/op/lexicals.t, in r13008:
pir_output_is(<<'CODE', <<'OUTPUT', 'find_lex: (Perl6 OUTER::)', todo
=> 'not yet implemented');
.sub main :main
.lex '$x', 42
get_outer()
.end

.sub 'get_outer' :outer('main')
.lex '$x', 13
$P0 = find_lex '$x', 1
say $P0
.end
CODE
42
OUTPUT

~jerry

Chip Salzenberg

unread,
Jun 23, 2006, 4:16:22 PM6/23/06
to jerry gay, p6i
On Fri, Jun 23, 2006 at 08:27:04AM -0700, jerry gay wrote:
> audreyt++ pointed out on #parrot that there doesn't seem to be a way
> to specify where to start finding lexicals, in support of perl's
> OUTER::. eg. (from S04):
> my $x = $OUTER::x;
> or
> my $x = OUTER::<$x>;

So OUTER:: is a -starting- point of one scope up? I thought it was a
specific notation that the $x you want is exactly one scope up, and if you
wanted two scopes up, you had to ask for OUTER::OUTER::<$x>.

Hm: what -is- the meaning of OUTER::OUTER::<$x> -- search starting two
scopes up, going as far as needed?

> i propose this should be specified using a three-arg form of find_lex
> <find_lex_p_s_i> where the third parameter is an integer specifying
> which level in the lexical chain to start the lookup.

I'm not fond of numeric scope counts, but they are cheap and solve this
specific problem. So, OK, and thanks for driving this with a test.
--
Chip Salzenberg <ch...@pobox.com>

Jerry Gay

unread,
Jun 23, 2006, 4:25:31 PM6/23/06
to Chip Salzenberg, p6i
On 6/23/06, Chip Salzenberg <ch...@pobox.com> wrote:
> On Fri, Jun 23, 2006 at 08:27:04AM -0700, jerry gay wrote:
> > audreyt++ pointed out on #parrot that there doesn't seem to be a way
> > to specify where to start finding lexicals, in support of perl's
> > OUTER::. eg. (from S04):
> > my $x = $OUTER::x;
> > or
> > my $x = OUTER::<$x>;
>
> So OUTER:: is a -starting- point of one scope up? I thought it was a
> specific notation that the $x you want is exactly one scope up, and if you
> wanted two scopes up, you had to ask for OUTER::OUTER::<$x>.
>
from #perl6:
13:21| audreyt: ?eval my $x = 3; { { say $OUTER::x } }
13:21| evalbot_10746: OUTPUT[3 ] Bool::True

boy, it's nice to have a reference implementation! yes, OUTER:: starts
the lookup one scope up.

> Hm: what -is- the meaning of OUTER::OUTER::<$x> -- search starting two
> scopes up, going as far as needed?
>

indeed.
my $x = 3; { { say $OUTER::x} } # 3

> > i propose this should be specified using a three-arg form of find_lex
> > <find_lex_p_s_i> where the third parameter is an integer specifying
> > which level in the lexical chain to start the lookup.
>
> I'm not fond of numeric scope counts, but they are cheap and solve this
> specific problem. So, OK, and thanks for driving this with a test.
> --

great, thanks!
~jerry

Jerry Gay

unread,
Jun 23, 2006, 4:27:11 PM6/23/06
to Chip Salzenberg, p6i
On 6/23/06, jerry gay <jerr...@gmail.com> wrote:
> indeed.
> my $x = 3; { { say $OUTER::x} } # 3
>
of course that should be
my $x = 3; { { say $OUTER::OUTER::x} } # 3

Patrick R. Michaud

unread,
Jun 23, 2006, 4:31:55 PM6/23/06
to Chip Salzenberg, jerry gay, p6i
On Fri, Jun 23, 2006 at 01:16:22PM -0700, Chip Salzenberg wrote:
> On Fri, Jun 23, 2006 at 08:27:04AM -0700, jerry gay wrote:
> > audreyt++ pointed out on #parrot that there doesn't seem to be a way
> > to specify where to start finding lexicals, in support of perl's
> > OUTER::. eg. (from S04):
> > my $x = $OUTER::x;
> > or
> > my $x = OUTER::<$x>;
>
> So OUTER:: is a -starting- point of one scope up? I thought it was a
> specific notation that the $x you want is exactly one scope up, and if you
> wanted two scopes up, you had to ask for OUTER::OUTER::<$x>.

My understanding is that $OUTER::x means "$x as it appears in the
outer lexical scope". In Perl 6 code, this means:

{
my $x = 4;
{
my $y = 7;
{
my $x = 9;
say $x; # outputs 9
say $OUTER::x; # outputs 4
say $OUTER::OUTER::x; # same thing
}
}
}

S02 says this in a somewhat roundabout way:

The current lexical symbol table is now accessible
through the pseudo-package MY. [...] The OUTER name refers
to the MY symbol table immediately surrounding the current
MY, and OUTER::OUTER is the one surrounding that one.

I interpret the first sentence as meaning that the "MY" pseudo-package
refers to all of the symbols in the current lexical scope, not
just those that have been explicitly declared in the current scope
using "my".

However, if there's confusion on this point then perhaps we should
kick the question to p6l or #perl6 for clarification.

Pm

Matt Diephouse

unread,
Jun 23, 2006, 4:43:03 PM6/23/06
to jerry gay, p6i
jerry gay <jerr...@gmail.com> wrote:
> audreyt++ pointed out on #parrot that there doesn't seem to be a way
> to specify where to start finding lexicals, in support of perl's
> OUTER::. eg. (from S04):
>
> my $x = $OUTER::x;
>
> or
>
> my $x = OUTER::<$x>;
>
> i propose this should be specified using a three-arg form of find_lex
> <find_lex_p_s_i> where the third parameter is an integer specifying
> which level in the lexical chain to start the lookup.

While you can't do this with find_lex currently, you *can* do it. Tcl
walks the lexpads to find lexicals. (See
languages/tcl/runtime/variables.pir):

.sub find_lex_pdd20
.param string variable_name

.local pmc interp, lexpad, variable
.local int depth
interp = getinterp
depth = 2 # we know it's not us or our direct caller.

get_lexpad:
# Is there a lexpad at this depth?
lexpad = interp["lexpad";depth]
unless_null lexpad, got_lexpad

# try again
inc depth
goto get_lexpad
got_lexpad:
variable = lexpad[variable_name]
.return(variable)
.end

Of course, that doesn't mean that I wouldn't like an opcode to do it for me. :-)

--
matt diephouse
http://matt.diephouse.com

Audrey Tang

unread,
Jun 23, 2006, 6:01:42 PM6/23/06
to Patrick R. Michaud, Chip Salzenberg, jerry gay, p6i

在 2006/6/23 下午 1:31 時,Patrick R. Michaud 寫到:

> I interpret the first sentence as meaning that the "MY" pseudo-package
> refers to all of the symbols in the current lexical scope, not
> just those that have been explicitly declared in the current scope
> using "my".

Same interpretation here, as S02 says $MY::foo is just $::foo which
is just a lexically-looked up $foo, it follows that MY::.keys will
contain all visible lexical symbols, which will be a subset of
OUR::.keys, instead of disjoint.

Some example code in S02 could help...

Thanks,
Audrey

PGP.sig

Nicholas Clark

unread,
Jun 24, 2006, 9:58:51 AM6/24/06
to ma...@diephouse.com, jerry gay, p6i
On Fri, Jun 23, 2006 at 01:43:03PM -0700, Matt Diephouse wrote:

> While you can't do this with find_lex currently, you *can* do it. Tcl
> walks the lexpads to find lexicals. (See
> languages/tcl/runtime/variables.pir):

[Parrot assembler implementation]

> Of course, that doesn't mean that I wouldn't like an opcode to do it for
> me. :-)

Is Parrot assembler considered a more productive language to write in than C?
If yes, is it logical to write opcodes such as this one in Parrot assembler
itself?

Nicholas Clark

Audrey Tang

unread,
Jun 24, 2006, 11:03:47 AM6/24/06
to ma...@diephouse.com, jerry gay, p6i
2006/6/24, Nicholas Clark <ni...@ccl4.org>:

Err, well, that will likely completely kill the performance. :-)

I had an implementation before Parrot had lexical pads, using global
variables and manual walking to emulate it. It was horribly slow.
Especially consider that Pugs currently compiles:

my $x; sub f { say $x; ...

to

my $x; sub f { say $OUTER::x; ...

because later in the scope $x may be declared, so it's safer to just
put OUTER right there.

Of course, if we cannot have an efficient OUTER lookup, we can always
do a post analysis on the block body and convert unneccessary OUTER::
away, but I don't think it's a good idea to force compile writers to
do that.

Thanks,
Audrey

Patrick R. Michaud

unread,
Jun 24, 2006, 11:41:44 AM6/24/06
to Audrey Tang, ma...@diephouse.com, jerry gay, p6i
On Sat, Jun 24, 2006 at 08:03:47AM -0700, Audrey Tang wrote:
> 2006/6/24, Nicholas Clark <ni...@ccl4.org>:

> >Is Parrot assembler considered a more productive language to write in than
> >C?
> >If yes, is it logical to write opcodes such as this one in Parrot assembler
> >itself?
>
> Err, well, that will likely completely kill the performance. :-)
>
> I had an implementation before Parrot had lexical pads, using global
> variables and manual walking to emulate it. It was horribly slow.
> Especially consider that Pugs currently compiles:
>
> my $x; sub f { say $x; ...
>
> to
>
> my $x; sub f { say $OUTER::x; ...
>
> because later in the scope $x may be declared, so it's safer to just
> put OUTER right there.

I don't think $x can be declared later in the scope. According to S04,

If you've referred to $x prior to the first declaration,
and the compiler tentatively bound it to $OUTER::x,
then it's an error to declare it, and the compiler is
allowed to complain at that point.

The Perl 6/Parrot compiler is simply using the find_lex opcode,
which of course does the outer lookups directly. OUTER comes into
play only when we need to explicitly exclude the current lexical
scope from the lookup.

> Of course, if we cannot have an efficient OUTER lookup, we can always
> do a post analysis on the block body and convert unneccessary OUTER::
> away, but I don't think it's a good idea to force compile writers to
> do that.

Part of me wonders if OUTER occurs frequently enough that it
needs a C-based opcode. However, given that we have at least
two languages (Perl 6 and Tcl) that are indicating they need
to be able to do OUTER lookups, it may deserve an opcode.

Pm

Nicholas Clark

unread,
Jun 24, 2006, 12:44:12 PM6/24/06
to Patrick R. Michaud, Audrey Tang, ma...@diephouse.com, jerry gay, p6i
On Sat, Jun 24, 2006 at 10:41:44AM -0500, Patrick R. Michaud wrote:
> On Sat, Jun 24, 2006 at 08:03:47AM -0700, Audrey Tang wrote:
> > 2006/6/24, Nicholas Clark <ni...@ccl4.org>:
> > >Is Parrot assembler considered a more productive language to write in than
> > >C?
> > >If yes, is it logical to write opcodes such as this one in Parrot assembler
> > >itself?
> >
> > Err, well, that will likely completely kill the performance. :-)

> Part of me wonders if OUTER occurs frequently enough that it


> needs a C-based opcode. However, given that we have at least

Which was sort of my question, although I wasn't clear.

> two languages (Perl 6 and Tcl) that are indicating they need
> to be able to do OUTER lookups, it may deserve an opcode.

Is it only possible to write parrot opcodes in C?

Nicholas Clark

Audrey Tang

unread,
Jun 24, 2006, 7:52:26 PM6/24/06
to Patrick R. Michaud, p6i, perl6-l...@perl.org

在 2006/6/24 上午 8:41 時,Patrick R. Michaud 寫到:

>> because later in the scope $x may be declared, so it's safer to just
>> put OUTER right there.
>
> I don't think $x can be declared later in the scope. According to
> S04,
>
> If you've referred to $x prior to the first declaration,
> and the compiler tentatively bound it to $OUTER::x,
> then it's an error to declare it, and the compiler is
> allowed to complain at that point.
>

Hmm, looks like it's been changed this April. In that case, indeed
the emitter can safely remove the implicit OUTER calls. Pugs's Parrot
backend has been updated accordingly. Thanks!

(...and Cc'ing p6l for the part below)

However, the spec wording is ambiguous:

$x = 1 if my $x;

The compiler is "allowed" to complain, but does that means it's also
okay to not die fatally, and recover by pretending as if the user has
said this?

# Current Pugs behaviour
$OUTER::x = 1 if my $x;

If it's required to complain, then the parser need to remember all
such uses and check it against declaration later, and it'd be better
to say that in the spec instead.

Thanks,
Audrey

PGP.sig

Patrick R. Michaud

unread,
Jun 24, 2006, 8:38:53 PM6/24/06
to Audrey Tang, p6i, perl6-l...@perl.org
On Sat, Jun 24, 2006 at 04:52:26PM -0700, Audrey Tang wrote:
> $x = 1 if my $x;
>
> The compiler is "allowed" to complain, but does that means it's also
> okay to not die fatally, and recover by pretending as if the user has
> said this?
>
> # Current Pugs behaviour
> $OUTER::x = 1 if my $x;

I think that a statement like C<< $x = 1 if my $x; >> ought to
complain.

Put slightly differently, if it's an error in any of the compilers,
it probably should be an error in all of them.

> If it's required to complain, then the parser need to remember all
> such uses and check it against declaration later, and it'd be better
> to say that in the spec instead.

I think that S04's phrase "then it's an error to declare it"
indicates that this should always be treated as an error. How/when
the compiler chooses to report the error is up to the compiler. :-)
That said, I wouldn't have any objection to removing or altering
"the compiler is allowed to complain at that point" phrase so
as to remove this particular ambiguity.

Pm

0 new messages