neolithos / neolua

A Lua implementation for the Dynamic Language Runtime (DLR).
https://neolua.codeplex.com/
Apache License 2.0
472 stars 76 forks source link

Allow forward declaration of local function #137

Closed ojb500 closed 3 years ago

ojb500 commented 3 years ago

Hi @neolithos

I had some problems with forward-declaration of local functions like this:

    local f
    function f()
        return 'Hello'
    end

    print(f()) -- expected 'Hello'; 'Can not call nil value' exception in NeoLua

This is required to support local mutual recursion. Similar code is given as an example in Programming in Lua and this seems to work ok in luac 5.3.3: https://www.ideone.com/JD0aKj

I think I have fixed this by being able to assign to an existing local when parsing a function statement.

This change also means that local functions can be redeclared, which wasn't possible before:

    local function f()
        return 'Hello'
    end
    local function f()
        return 'World'
    end
    print(f()) -- expected 'World'; NeoLua fails to compile

Now a function statement will not escape into the global scope if we have a local:

        local f1, f2
        function f2()
            return f1()
        end
        function f1()
            return 'Hello'
        end
        return _G['f2'] == nil -- expected 'true'; NeoLua returns 'false'

The only thing I'm not sure about is if it is correct to pass true to scope.LookupExpression, or whether we could also bind to a local in a deeper scope.

Thank you @neolithos for your work on this excellent project!

best regards

Oliver

ojb500 commented 3 years ago

After some more investigations I found that this should assign to the local:

local f
function g()
    function f()
        return 'Hello'
    end
end
g()
print(_G['f'] == nil) -- expected 'true'
print(f()) -- expected 'Hello'

So we should be able to assign a function to a local variable in any enclosing scope.

neolithos commented 3 years ago

I will take a closer look on this, in the next days. But it looks really good.

Thank you!

neolithos commented 3 years ago

Thank you. Good job.

I pushed a prerelease, for tests.