hi,
recently on #parrot there was a short discussion on symbol handling
w.r.t. nested scopes.
During that discussion, I understood that when looking for a symbol in
a PAST::Block node, it will look in that block, and, if not found, in
any :outer blocks.
To give an example:
function foo {
var a;
{
a = 42; # this a is declared in this block's outer scope, namely
the scope block of function foo.
}
}
When looking at the actual implementation of the symbol() method on
PAST::Block (which does symbol storing and retrieving),
there is no proof of such behavior. In fact, I spent a few hours
figuring why nested blocks didn't work in my private language project.
So, my question now is, what should symbol() be doing? Should it stay
as-is, or am I missing a point somewhere?
If the current implementation is correct, then when looking for a
symbol "inside-out" (scope-wise) should be implemented as a while
loop, something I had understood to be implemented in PAST. This could
look like this:
$scope := 'package' # default scope is package
$index := [EMAIL PROTECTED]; # find number of blocks on "scope stack"
while $index != 0 {
$index := $index - 1;
if @?BLOCK[$index].symbol($name) { # look for symbol in "innermost" scope
$scope := 'lexical'; # if found, scope is lexical.
}
}
kjs
PS: For reference, I included the implementation of the symbol method,
found in compilers/pct/src/PAST/Node.pir:
.sub 'symbol' :method
.param string name
.param pmc attr :slurpy :named
.local pmc symtable
symtable = self['symtable']
unless null symtable goto have_symtable
symtable = new 'Hash'
self['symtable'] = symtable
have_symtable:
if attr goto set_symbol
get_symbol:
$P0 = symtable[name]
if null $P0 goto set_symbol
.return ($P0)
set_symbol:
symtable[name] = attr
.return (attr)
.end