ZeroBraneStudio icon indicating copy to clipboard operation
ZeroBraneStudio copied to clipboard

Request: Support for custom API function overloading and operators

Open Silverlan opened this issue 7 years ago • 3 comments

As far as I can tell, neither of these are possible at the moment. Below is a nonsense example I wrote for testing:

return {
	Vector = {
		type = "class",
		description = "Vector class",
		childs = {
			Rotate = {
				type = "method",
				description = "Rotates this vector.",
				args = "(EulerAngles)"
			},
			Rotate = {
				type = "method",
				description = "Rotates this vector.",
				args = "(Quaternion)"
			},
			Rotate = {
				type = "method",
				description = "Rotates this vector by an axis-angle.",
				args = "(Vector,number)"
			}, -- Overwrites the two previous overload definitions
			__mul = {
				type = "function", -- I've also tried it as a method
				description = "Multiply",
				args = "(Vector,Vector)",
				returns = "(Vector)",
				valuetype = "Vector"
			}
		}
	}
}

And the Lua Test-Code in ZeroBrane:

  local v0 = Vector()
  local v1 = Vector()
  local v2 = v0.__mul(v1) -- 'v2' is correctly recognized as a Vector object
  v2:Rotate(v0,1.0) -- Only one overload is shown
  
  local v3 = v0 *v1
  -- 'v3' is NOT recognized as a Vector object

The function overloading would be especially useful for programs which are using Luabind.

Silverlan avatar Jun 16 '17 16:06 Silverlan

:warning: Just one note:

childs = {
	Rotate = {
		:::
	},
	Rotate = {
		:::
	},
	Rotate = {
		:::
	}, -- Overwrites the two previous overload definitions
}

This is not possible because of the lua language (In a table a key can only occure once). The last assignment will overwrite the first ones. What about this alternative?

Rotate = {
	type = "method",
	description = "Rotates this vector.",
	-- multiple possible args
	args = { "(EulerAngles)","(Quaternion)","(Vector,number)"}
},

jjvbsag avatar Jul 31 '17 18:07 jjvbsag

When facing a similar problem in Cuberite's API description, we opted for supporting two kinds of syntax:

fnName =
{
  Params = ...,
  Returns = ...,
  Notes = ...,
},
overloadedFnName =
{
  {
    Params = ...,
    Returns = ...,
    Notes = ...,
  },
  {
    Params = ...,
    Returns = ...,
    Notes = ...,
  },
},

Then, whoever uses these definitions does a simple unification:

-- apiDesc is either the fnName or overloadedFnName table above
local fnDescs = apiDesc[1] and apiDesc or { apiDesc }
-- fnDescs is now normalized to always be an array-table of simple descriptions
for idx, desc in ipairs(fnDescs) do
  processFn(desc.Params, desc.Returns, desc.Notes)
end

madmaxoft avatar Jul 31 '17 21:07 madmaxoft

__mul = {
:::
		}

:+1: I really like this. Would be great for some project of me. Assume talking about Amounts of money (defined by a numeric value and a currency symbol). Take this

local price_A=AMOUNT(0.67,'€'),
local price_B=AMOUNT(0.50,'€'),
print(price_A+price_B) -- gives 1.17€
print(price_A-price_B) -- gives 0.17€
print(price_A*5) -- gives 3.35€
print(price_A/2) -- gives 0.34€ (rounding :-) )
print(price_A/price_B) -- gives 1.34 (a number !)

the last two lines are interesting, because depending on the arguments the type of returned result varies. My suggestion args = { "(EulerAngles)","(Quaternion)","(Vector,number)"} does not manage this. overloadedFnName would.

jjvbsag avatar Aug 01 '17 06:08 jjvbsag