Skip to content

for loop misbehavior #514

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

Open
2 tasks done
faelys opened this issue Dec 10, 2024 · 0 comments · May be fixed by #528
Open
2 tasks done

for loop misbehavior #514

faelys opened this issue Dec 10, 2024 · 0 comments · May be fixed by #528

Comments

@faelys
Copy link

faelys commented Dec 10, 2024

You must post issues only here. Questions, ideas must be posted in discussions.

  • GopherLua is a Lua5.1 implementation. You should be familiar with Lua programming language. Have you read Lua 5.1 reference manual carefully?
  • GopherLua is a Lua5.1 implementation. In Lua, to keep it simple, it is more important to remove functionalities rather than to add functionalities unlike other languages . If you are going to introduce some new cool functionalities into the GopherLua code base and the functionalities can be implemented by existing APIs, It should be implemented as a library.

Please answer the following before submitting your issue:

  1. What version of GopherLua are you using? : Usually v1.1.1, but I reproduced it with v1.1.2-0.20241109074121-ccacf662c9d2
  2. What version of Go are you using? : 1.23.0
  3. What operating system and processor architecture are you using? : linux/amd64
  4. What did you do? : two consecutive for loops with a bare function call
  5. What did you expect to see? : the function should be called with two nil arguements at the beginning of each loop, that's what I get with lua interpreter 5.1.5 from Ubuntu 22.04 repository
  6. What did you see instead? : at the beginning of the second loop, the function is called with the same non-nil second argument as in the last iteration of the first loop.

Here the small demonstrator I built:

tab = {foo = 42, bar = "baz" }
fn = function(s,k)
        print ("(s)" .. tostring(s))
        print ("(k)" .. tostring(k))
        k,_ = next(tab,k)
        return k
end

for item in fn do
        print(item)
end

for item in fn do
        print(item)
end

Here is its output when run using lua 5.1.5, where the two loops are correctly run:

(s)nil
(k)nil
bar
(s)nil
(k)bar
foo
(s)nil
(k)foo
(s)nil
(k)nil
bar
(s)nil
(k)bar
foo
(s)nil
(k)foo

Here is its output when run using GopherLua:

(s)nil
(k)nil
foo
(s)nil
(k)foo
bar
(s)nil
(k)bar
(s)nil
(k)bar

As can be seen, at the beginning of the second loop, fn is called with nil and "bar", finishing the loop early.

Adding a print statement between the two loops seems to avoid the issue

FWIW, I discovered the issue with a custom go iterator in the __call metatable of a global, but having reproduced it in pure Lua without the mess I created in the interpreter makes me think the issue is with the interpreter rather than my constructs.

faelys added a commit to faelys/gopher-lua that referenced this issue Mar 22, 2025
Use `nvars` as the assignment numbers rather than `lennames`.

This makes no difference in `compileLocalAssignStmt` as the numbers are
equal, but in `compileGenericForStmt` the names are the iteration
variables while `nvars` refers to the local generator, state, and
control. The iteration variables feel a bit out of place here.

The whole body of `compileRegAssignment` seem inconsistent, using
`names` only for its length, and mixing `lennames` and `nvars` in
surprising ways.

Moreover the function name `compileRegAssignment` suggests assigning to
registers rather than names, so I dropped `lennames` entirely to use
only `nvars`.
@faelys faelys linked a pull request Mar 22, 2025 that will close this issue
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

Successfully merging a pull request may close this issue.

1 participant