Is there a way to introspect a function in Lua? - lua

I am creating a game in love2d (LuaJIT) and I am creating a debug window for changing values at runtime. I was able to do that, however, I also now want to be able to call functions. For example, I traverse a table and there is a function in this table called "hello" which is written like this:
self.hello = function(str, num)
print(string.format("%s: %d", str, num))
end
From the expression of type(object.hello) I only see function. If it had been a table, I could have traversed it and see the keys and values, but it is just a "function" and I have no idea how to properly call it, as I don't know what arguments does it take and how many. Is there a way to find this out at runtime in lua? Maybe this information is also stored in some table elsewhere?

it is just a "function" and I have no idea how to properly call it
Neither does Lua. As far as Lua is concerned, any Lua function can take any number of parameters and return any number of parameters. These parameters could be of any type, as could its return values.
Lua itself does not store this information. Or at least, not in any way you could retrieve without doing some decompiling of its byte-code. And since you're using LuaJIT, that "decompiling" might require decompiling assembly.

Related

How do I change a pre-defined variable in a table in Luau?

In a Roblox game I'm programming, I want to have a table of boolean values to iterate over ensuring that they're all false before making another one true, e.g.;
local bool1 = true
local bool2 = false
local bool3 = false
local bool4 = false
local tbl1 = {}
table.insert(tbl1,boolX) -- where "X" is the number above, did this in interest of shortening
for i,v in pairs(tbl1) do
if v then v = not v end
end
However, as stated in the penultimate paragraph of section 2.1 of the 5.3 manual (knowing, albeit, that Luau uses 5.1 as its base);
Tables, functions, threads, and (full) userdata values are objects: variables do not actually contain these values, only references to them. Assignment, parameter passing, and function returns always manipulate references to such values; these operations do not imply any kind of copy.
That in mind, that means that I'm not actually shoving bool1 through bool4 into the table, just their values; the table would look like {true, false, false, false}. This means that I can't simply write a loop to iterate through the table and invert any trues I find;
local bool1 = true
local tbl1 = {}
table.insert(tbl1,bool1)
tbl1[1] = false
print(bool1)
print(tbl[1])
--output:
-- true
-- false
I should point out that I very well could just shove all my variables into one giant if/else and call it a night, but that is a lot of variables to check, a lot of typing, and I can't think of any other more elgant and less tedious way other than finding a form of iteration over them all.
I want to be able to have an actual reference, in some form, to the actual variables so that I can modify them from within the table and make them iterable.
I've attempted to follow the examples given in the best answer to this question, with no successes. I would need to be able to, and cannot with these examples, substitute for any given variable at any given time, rather than just having one or two I want declated and thus returned as shown. I've attempted wrapping them in a function to provide my table and variable as arguments, but that doesn't seem to have any effect; it either outputs nothing, or nil.
The following answer after has one example that seems like it could work, but overall is pointless for what I'm trying to achieve; I don't want to re-declare or re-assign the variables I already have, I just want to return the specific value.
I've attempted using a key/value pair, making the key the potential variable name and making it equal the variable's value, but I've no way to make that key return a variable of the same name. I even attempted merging this method and the setmetatable method mentioned in the first set of examples to see if I couldn't substitute from there, to no avail.
I should point out that, while I'm not a complete newbie to Lua or Luau, I'm also not an expert in the field by any meaning of the word; I'll catch on quick, but where possible, explain like I'm 10.
The only way to iterate over local variables that are not referenced by table fields, is to use debug.getlocal in a loop.
Opinionated:
But this is a very bad approach to your problem.
You should refactor the code. If you need to update a list of variables have them in a list from the start. Don't be afraid of refactoring. Improving things usually pays off on the long term.
If your codebase is so bad that you are afraid of putting a few variables into a table you should really think over the design.
There is no way to do this in Roblox Luau.
Any potential way to do so in standard Lua is impossible to do in Luau due to how heavily sandboxed the latter is compared to the former.
Possible solutions that were recommended via comments include: making the variables needed available in _G as globals, then using them there; or using a pointer value in the table equivalent to the one you want, even though it won't technically change the value you want itself.
Another answer recommends the use of debug.getlocal() for standard Lua, but doesn't work in Luau; keep this in mind when attempting to use it, as you will get an attempt to call a nil value error.
The recommended way to do this is not to do it at all, and instead have your variables and/or values in your table from the start.
Not only does this provide ease-of-access in many cases, but it will allow you to iterate through them significantly easier than trying to shove them into tables and the like. Refactoring, if you need to do something similar to this, is highly recommended across the board.

How do I reverse tostring(table) in Lua

In Lua when you use the method tostring(table) it returns something like this: table: 0xb5b1f0. So I was wondering if there is any way of reversing this and turning it back into the regular table.
This actually prints the pointer to the table data as a hex integer. You cannot use the numeric value of a pointer in Lua to access the data directly (in a standard way).
If you are really interested, you can serialize (convert a table to a string) (recursively), and then back into a table, but that is much less convenient than an 8 digit hex. If you are using any framework or library, there is a good chance that it comes with a built-in table serialization function. If not, then just look up "lua table serialization function" on any search engine. (I'll find a good function and write it here)
Something else you might want to know, is that you can do something like this with functions: string.dump will dump the Lua binary for the function in a Lua string, and can then later be converted to a function using loadstring().

Lua: Get a table address within Lua without tostring

I am creating a caching system for complex shapes in Lua and I want it to be backwards compatible as a plug and play replacement for the default, non cached system, to increase performance. I've successfully rendered an object with 6.4 million points which gets turned into 3.1 million trapezoids to make a shape instead of using 6.4 million triangles, cache it and continue rendering without any performance hit beyond initial caching.
I want to set up a cached data table which uses the reference to the original table as the index. The problem is, if I use tostring, I end up with the entire table as a nicely formatted human-readable string which wouldn't be nice to use as a short index to reference the table.
I do not want to require the dev to assign an ID to the object because the default system doesn't do this, and it is an extra step which can be avoided by simply using the address which is unique to that object anyways..
I can not find a Lua implementation of lua_topointer(L, idx)... but maybe I'm missing something?
A few issues - my tostring no longer shows table: 0x12345678
I have rewritten a lot of meta-functions and __tostrings to output the data for debugging purposes. But, on Lua demo I can't find the exact function which replaces this behavior, and I didn't replace print in my latest version. So print is default, etc...
On Lua demo I have also tried getmetatable table, function m:__tostring( ) return 'blah' end
and print( { } ), print( tostring( { } ) )
The first prints the address. The second prints blah. So because print isn't using tostring, by default, what is it using? Is that accessible via Lua?
If all else fails, I'll probably have to get rid of my __tostring table metamethod and make a secondary function to output that particular data type which defaults the purpose of having a __tostring method for everything ( and the fact that print ignores it; one of the reasons I rewrote print in an old version... but I reverted to keep it default )
So, does anyone know a Lua function I can call, which is not tostring, which can get the address of a table in Lua? It must return the value so it can be used.

Lua Terminology related to OOP

To be to the point; I've done Lua for awhile, but never quite got the terminology down to specifics, so I've been Googling for hours and haven't come up with a definitive answer.
Related to OOP in Lua, the terminology used include:
Object
Class
Function
Method
Table
The question is, when are these properly used? Such as in the example below:
addon = { }
function addon:test_func( )
return 'hi'
end
Q: From my understanding with Lua and OOP, addon is a table, however, I've read that it can be an object as well -- but when it is technically an object? After a function is created within that table?
Q: test_func is a function, however, I've read that it becomes a "Method" when it's placed within a table (class).
Q: The entire line addon:test_func( ), I know the colon is an operator, but what is the term for the entire line set of text? A class itself?
Finally, for this example code:
function addon:test_func( id, name )
end
Q: What is id and name, because I've seen some people identify them as arguments, but then other areas classify them as parameters, so I've stuck with parameters.
So in short, what is the proper terminology for each of these, and when do they become what they are?
Thanks
From my understanding with Lua and OOP, addon is a table, however, I've read that it can be an object as well -- but when it is technically an object? After a function is created within that table?
Object is not a well-defined term. I've seen it defined (in C) as any value whatsoever. In Lua, I would consider it synonymous with a table. You could also define it as an instance of a class.
test_func is a function, however, I've read that it becomes a "Method" when it's placed within a table (class).
You're basically right. A method is any function that is intended to be called with the colon notation. Metamethods are also methods, because, like regular methods, they define the behavior of tables.
The entire line addon:test_func( ), I know the colon is an operator, but what is the term for the entire line set of text? A class itself?
There's no name for that particular piece of code. It's just part of a method definition.
Also, I wouldn't call the colon an operator. An operator would be the plus in x + y where x and y both mean something by themselves. In addon:test_func(), test_func only has meaning inside the table addon, and it's only valid to use the colon when calling or defining methods. The colon is actually a form of syntactic sugar where the real operator is the indexing operator: []. Assuming that you're calling the method, the expansion would be: addon['test_func'](addon).
What is id and name, because I've seen some people identify them as arguments, but then other areas classify them as parameters, so I've stuck with parameters.
They're parameters. Parameters are the names that you declare in the function signature. Arguments are the values that you pass to a function.

Details about function arguments through Lua C API

if I call a function foo(t[1]) through the C API, can I in any way see what table and what index is as argument, in this case t and 1?
The problem at hand is a function move_card(card, table_slots[0]) where I move a card from one slot on a game area to another one. table_slots can also be hand or player_slots. This can be solved using a metatable, stating the name of the table being accessed. But the index is impossible to solve, or is it? table_slots[0] can be a card table, or an overlay or stack (arrays of cards), or nil if it's empty, as could player_slots. But what I need to know is in fact if it's from a table_slots or player_slots.
Could I hack some code analysis? Like, get the line where the function call is made, and then grep the index through a regexp? I could send table_slots[0] as a string, also, like move_card(card, "table_slot[0]"). Not as elegant, but still working.
No, once a value reaches a function, be it C or Lua, its origins are lost.
On the other hand, when an error occurs in Lua, the runtime system tries quite a bit to reconstruct the origin of the relevant values, but it does not always succeeds.

Resources