Skip to content
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

@operator add customization for first operand? #2777

Closed
SeanTheBuilder1 opened this issue Aug 2, 2024 · 5 comments
Closed

@operator add customization for first operand? #2777

SeanTheBuilder1 opened this issue Aug 2, 2024 · 5 comments
Labels
enhancement New feature or request

Comments

@SeanTheBuilder1
Copy link
Contributor

How are you using the lua-language-server?

NeoVim

Which OS are you using?

Linux

What is the issue affecting?

Annotations

Expected Behaviour

I expected it would work like this

---@class Vector3
---@field x number
---@field y number
---@field z number
---@operator add(Vector, Vector3): Vector3 # Vector3 + Vector3
---@operator add(number, Vector3): Vector3 # number + Vector3
---@operator add(Vector3, number): Vector3 # Vector3 + number
Vector3 = {}

Actual Behaviour

But instead it is like this

---@class Vector3
---@field x number
---@field y number
---@field z number
---@operator add(Vector): Vector3 # Vector3 + Vector3
---@operator add(number, Vector3): Vector3 # this is impossible as far as I know
---@operator add(number): Vector3 # Vector3 + number
Vector3 = {}

Reproduction steps

copy paste 'Expected Behaviour code'
displays " ')' expected "

Additional Notes

I am asking if the impossible case is actually possible and that it is only undocumented or something. I expected the binary operators to take two parameters instead of just one. Thank you.

Log File

No response

@CppCXY CppCXY added the enhancement New feature or request label Aug 2, 2024
@tomlau10
Copy link
Contributor

tomlau10 commented Aug 3, 2024

From lua-users wiki, these kinds of mathematic operators will check metatables on both side (the left value first, then the right).
http://lua-users.org/wiki/MetatableEvents

  • __add - Addition. When writing "myTable + object" or "object + myTable", if myTable's metatable has an __add key pointing to a function, that function is invoked (passing the left and right operands in order) and the return value used.
    • ''If both operands are tables, the left table is checked before the right table for the presence of an __add metaevent.

With a bit of digging in LuaLS codebase, I think this functionality can be added here:

local node = vm.runOperator(binaryMap[op], source[1], source[2])
if node then
vm.setNode(source, node)
return
end

  • After running once using source[1], source[2], if no matched result found, we can run it again using source[2], source[1]
local node = vm.runOperator(binaryMap[op], source[1], source[2])
if not node and op == '+' then
    -- interchangeable for '+'
    node = vm.runOperator(binaryMap[op], source[2], source[1])
end
if node then
    vm.setNode(source, node)
    return
end

I tested this and it works 👀

---@class Vector3
---@field x number
---@field y number
---@field z number
---@operator add(Vector3): Vector3 # Vector3 + Vector3
---@operator add(number): Vector3 # Vector3 + number | number + Vector3
Vector3 = {}

local a = 1 + Vector3
local b = 1.1 + Vector3
local c = (1*2+3) + Vector3

local x ---@type number
local d = x + Vector3

-- a, b, c, d are all inferred as `Vector3`

Note that the above demo code I only check for + operator, and from the lua user wiki, this interchangeable logic applies to: __add, __sub, __mul, __div, __mod, __pow, __concat. I suggest @SeanTheBuilder1 can try to work on this and open a PR after testing 👍

@SeanTheBuilder1
Copy link
Contributor Author

This is an interesting find and I find it a good enough workaround for now while #1371 is still being worked on for the asymmetric operations. Added that with that preliminary code snippet would make the LSP in line with the actual behavior of lua code.

@SeanTheBuilder1
Copy link
Contributor Author

whoops misclick i apologize

@tomlau10
Copy link
Contributor

tomlau10 commented Aug 3, 2024

I have never thought of an asymmetric __add ... what could be a possible use case for that 😂 ?

@SeanTheBuilder1
Copy link
Contributor Author

Good day, yeah I couldn't think of a practical one either but that might be an edge case for the future. Technically you could do that with a C binding where it returns a different type when it detects if it was the left or right operand. But that might be too weird, after all I'm just trying to have parity with a library I'm interfacing which has support for scalars on the left operand and so far I can't find a case which breaks symmetry.

sumneko added a commit that referenced this issue Aug 6, 2024
feat: flip binary operator check if failed (#2777)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants