edubart / nelua-lang

Minimal, efficient, statically-typed and meta-programmable systems programming language heavily inspired by Lua, which compiles to C and native code.
https://nelua.io
MIT License
1.99k stars 64 forks source link

Support actual closures via struct #267

Open cattokomo opened 2 months ago

cattokomo commented 2 months ago

WARNING: Please, read this note carefully before submitting a feature request:

It is important to realize that this is NOT A SUPPORT FORUM, this is for ISSUES ONLY.

If you need support, have questions, ideas to discuss you should use the Nelua Discussions forum or the Nelua Discord server.

Please, before submitting a new issue, verify the following:


Feature motivation

It's known that Nelua does not support closures. Once you had a closure in your code, Nelua will complain about that it can't handle closures.

test.nelua:10:5: from: AST node Block
    return x
    ^~~~~~~~
test.nelua:10:12: error: attempt to access upvalue 'x', but closures are not supported
    return x

Feature description

But with records, we can somewhat implement a type of closure in Nelua.

local function add(x: integer)
  local closure = @record{
    -- Generated field
    x: integer
  }

  function closure.closure(y: integer)
    return self.x + y
  end

  return (@closure)({x})
end

So if you have a function with closure like this.

local function idiv(x: integer)
  return function(y: integer)
    return x // y
  end
end

Nelua should generate the following code as this.

local function idiv(x: integer)
  local closure = @record{x: integer}

  function closure:closure(y: integer)
    return self.x // y
  end

  return (@closure)({x})
end

And then will use closure.closure as closure when it's returned from function.

Code example

Provide minimal code example for the feature. Please, format the code properly and try to keep it as simple as possible, just focusing on the feature.

local function add(x: integer)
  return function(y: integer)
    return x + y
  end
end

print(add(1)(2))

Will generate a code (in C but this is explained in Nelua).

local function add(x: integer)
  local closure = @record{
    x: #[x.type]#
  }

  function closure:closure(y: integer)
    return self.x + y
  end

  return (@closure)({x})
end

print(add(1):closure(2))

Describe alternatives you've considered

A clear and concise description of any alternative solutions you've considered.