On Wed, Sep 24, 2008 at 12:09:37PM +0200, François Perrad wrote:
> Currently, the bigger issue in Lua on Parrot is lexical or upvalue in  
> Lua jargon (the reason for Lua on Parrot is not really Lua).
> The following Lua code doesn't give the expected result (from  
> languages/lua/t/closure.t) :
>     a = {}
>     local x = 20
>     for i=1,10 do
>         local y = 0
>         a[i] = function () y=y+1; return x+y end
>     end
>
>     print(a[1]())
>     print(a[1]())
>     print(a[2]())
>
>     --[[
>     The loop creates ten closures (that is, ten instances of
>     the anonymous function). Each of these closures uses
>     a different y variable, while all of them share the same x.
>     ]]
>
>
> With the current Parrot, I never found a way to do it.
>
> So, I'll be happy if this revisiting handles this issue.


Here's how I would expect this to look in PIR under the
new scheme (I'm not familiar with Lua, but I'm assuming 'local' 
in Lua means 'lexical', and that the loop variable is lexical):

.sub 'main'
    ##  set outer context of forbody_block
    .const .Sub forbody = 'forbody_block'
    capture_lex forbody

    ##  a = {}
    .local pmc a
    a = new 'ResizablePMCArray'
    store_global 'a', a 

    ##  local x = 20
    .local pmc x
    x = new 'Integer'
    x = 20
    .lex 'x', x

    ##  for i = 1,10 do
    .local pmc i
    i = new 'Integer'
    .lex 'i', i
  for_loop:
    if i > 10 goto for_done
    forbody()
    inc i
    goto for_loop
  for_done:

    ##  print(a[1]())
    $P0 = a[1]
    $P1 = $P0()
    say $P1

    ## ...
.end


.sub 'forbody_block' :outer('main')
    ##  set outer context of lambda_block
    .const .Sub lambda = 'lambda_block'
    capture_lex lambda

    ##  local y = 0
    .local pmc y
    y = new 'Integer'
    y = 0
    .lex 'y', y

    ##  a[i] = function () y = y+1; return x+y; end
    .local pmc a,i
    a = get_global 'a'
    i = find_lex 'i'
    $P0 = clone lambda           ## this creates the closure
    a[i] = $P0
.end


.sub 'lambda_block' :outer('forbody_block')
    ##  y = y + 1;
    .local pmc y
    y = find_lex 'y'
    n_add $P0, y, 1
    copy y, $P0

    ##  return x+y; 
    .local pmc x
    x = find_lex 'x'
    n_add $P1, x,y
    .return ($P1)
.end



Pm

Reply via email to