Getting all functions in a Lua script - function
I'm trying to figure out a way to get all functions in a Lua script. This script has been compiled into a function through loadfile. For example, I'd want to get every function defined in the script below.
function example1()
end
local function example2()
end
local library = {}
function library:example3()
end
(function()
-- Functions like this too.
end)
The names aren't important, I'm just looking for a way to get the actual functions so I can use them in debug.getinfo and get information like the lines they were defined in. I have LuaJIT, if that makes this any easier. Is something like this even possible? Thanks in advance.
I guess the file declares its functions as global, or it would be really easy to track what is returned.
If that's the case, you can cycle through all the global items with a generic for loop, and only take the functions from them:
allFuncs = {}
for key, item in pairs(_G) do
if type(item) == "function" then
allFuncs[#allFuncs + 1] = item
end
end
(_G is the table holding all the global variables)
Then you will have a list (allFuncs) holding all the functions declared, but be aware that it will also contain default functions like setmetatable or xpcall.
It's easy to modify the code to not make this happen, but only use this for testing / learning:
function allFuncs()
local funcsTab = {}
for key, item in pairs(_G) do
if type(item) == "function" then
funcsTab[#funcsTab + 1] = item
end
end
return funcsTab
end
defaultFuncs = allFuncs()
--then you load your file: other functions get declared
--we create another table containg the default + the new functions
myFuncs = allFuncs()
--then you subtract the first table from the second
for i = 1, #myFuncs do
for o = 1, #defaultFuncs do
if myFuncs[i] == defaultFuncs[o] then
table.remove(myFuncs, i)
end
end
end
This is if your file doesn't return anything and declares its functions as globals.
If the file declares them as local and then returns a table containing them, just use the first piece of code replacing _G with that returned table.
This is not likely to be possible without syntax or bytecode analysis as each function definition is an assignment (just has different forms in your examples). See the bytecode inspector and a related discussion here. For the syntax analysis you can use metalua or something like lua-loose-parser. Keep in mind that even those tools won't give you the entire list of functions as some functions may be defined dynamically using loadstring (or similar methods).
If you only have access to the result of loadfile, then you best bet is to use the bytecode analyzer.
This is possible using jit.attach in LuaJIT.
You can attach callbacks to a number of compiler events with
jit.attach. The callback can be called:
when a function has been compiled to bytecode ("bc");
when trace recording starts or stops ("trace");
as a trace is being recorded ("record");
or when a trace exits through a side exit ("texit").
http://wiki.luajit.org/JIT-Compiler-API#jit-attach
jit.attach(function(f)
local funcInfo = jit.util.funcinfo(f)
end, "bc")
Related
Proper way to dynamically define LUA functions
I have been playing with Lua for the past week and I ended up writing this peace of code. I find it really useful that you can dynamically create new functions that "inherit" other functions, so programmers must have a name for it. My questions are: What is this called? Is there a better way to do this? (cycle over a data structure and create add-on functions that "improve" existing functions) D = { name = { value = nil, offset = 0, update = function (self) self.value = "Berlin" end, }, } --Dynamic function definition for i in pairs(D) do D[i].upAndWrite = function(self) self:update() print("upAndWrite was here") end end print(D.name.value) D.name:upAndWrite() print(D.name.value) Result: nil upAndWrite was here Berlin
I don't think that what you're doing have special name for it, it's just on-the-fly function creation. There are few notes regarding your code: Proper for loop for i in pairs(D) do … end In programming, variable i is generally used for counter loops, like in for i=1,100 do … end Here, pairs returns an iterator function and the idiomatic way to use it is for k,v in pairs(D) do … end Here k is a key (like i in your code) and v is a value (use it instead of indexing table like D[k] or D[i] in your code when you need to access the corresponding value). There's no need to create functions on the fly! Another important thing is that you create new function on each loop iteration. While this feature is very powerful, you're not using it at all as you don't store anything using upvalues and only access data through arguments. A better way to do it would be creating function once and assigning it to every field: -- Define D here do local function upAndWrite(self) self:update() print("upAndWrite was here") end for k,v in pairs(D) do v.upAndWrite = upAndWrite -- Use our function end end -- Perform tests here What does on-the-fly function creation allow? As mentioned above, you can utilize this very powerful mechanism of closures in certain situations. Here's a simple example: local t = {} for i = 1, 100 do -- Create function to print our value t[i] = function() print(i) end -- Create function to increment value by one t[-i] = function() i=i+1 end end t[1]() -- Prints 1 t[20]() -- Prints 20 t[-20]() -- Increment upvalue by one t[20]() -- Now it is 21! This example demonstrates one possible usage of upvalues and the fact that many functions can share them. This can be useful in a variety of situations together with the fact that upvalues can't be changed by side code (without use of debug library) and can be trusted in general. I hope my answer covers what you wanted to know. Note: Also, this language is called Lua, not LUA.
As a whole it doesn't have a name, no. There's lots of concepts that play into this: First Class Functions aka. functions that can be assigned to variables and passed around just like numbers or strings. Anonymous Functions aka. functions that are created without giving it a name explicitly. All functions in Lua are technically anonymous, but often they are assigned into a variable right after creation. Metaprogramming aka. writing programs that write programs. A loop that creates functions (or methods) on an arbitrary number of objects is very simple, but I'd count it as metaprogramming. Lua Tables; this may seem obvious, but consider that not all languages have a feature like this. Javascript has objects which are similar, but Ruby for example has no comparable feature. If you're gonna use pairs, you might as well make use of both variables. for key, object in pairs(D) do function object:upAndWrite(self) self:update() print("upAndWrite was here") end end Though that would create many closures, which means more work for the garbage collector, more memory usage and slower execution speed. for key, object in pairs(D) do print(object.upAndWrite) -- All the functions are different end It's a good first stage, but after refactoring it a bit you could get this: do local method = function(self) -- Create only one closure self:update() print("upAndWrite was here") end for key, object in pairs(D) do object.upAndWrite = method -- Use single closure many times end end Now there's only one closure that's shared among all the tables. for key, object in pairs(D) do print(object.upAndWrite) -- All the functions are the same end
List Lua functions in a file
How can I list all the functions included in a Lua source file? For example, I have fn.lua which contains function test1() print("Test 1") end function test2() print("Test 2") end And I wish to be able to display those function names (test1, test2) from another Lua script. The only way I can figure at the moment is to include the file using require, then list the functions in _G - but that will include all the standard Lua functions as well. Of course I could just parse the file manually using the string search functions, but that doesn't seem very Lua to me! This will eventually form part of a process that allows the developer to write functions in Lua, and the operator to select which of those functions are called from a list in Excel (yuk!).
If you put them all in a "module" (which you should probably do, anyway): mymodule = { } function mymodule.test1() print("Test 1") end function module.test2() print("Test 2") end return mymodule It becomes trivial: mymodule = require"mymodule" for fname,obj in pairs(mymodule) do if type(obj) == "function" then print(fname) end end If you absolutely have to keep them in raw form, you'd have to load them in a different way to separate your global environment, and then iterate over it in a similar way (over the inner env's cleaned _G, perhaps).
I see three ways: Save the names in _G before loading your script and compare to the names left in _G after loading it. I've seen some code for this, either in the Lua mailing list or in the wiki, but I can't find a link right now. Report the globals used in a function by parsing luac listings, as in http://lua-users.org/lists/lua-l/2012-12/msg00397.html. Use my bytecode inspector lbci from within Lua, which contains an example that reports globals.
If you want to do this, it's better to define the function is a package, as described in Programming in Lua book: functions = {} function functions.test1() print('foo') end function functions.test2() print('bar') end return functions Then you can simply iterate your table functions.
'Invalid Handle object' when using a timer inside a function in MatLab
I am using a script in MatLab that works perfectly fine by itself, but I need to make a function out of it. The script read a .csv file, extract all values, start a timer, and at each tick displays the corresponding coordinates extracted from the .csv, resulting in a 3D animation of my graph. What I would like is to give it the location of the .csv, so that it starts displaying the graphs for this csv. Here is what I have come up with: function handFig(fileLoc) csv=csvread(fileLoc,1,0); both = csv(:,2:19); ax=axes; set(ax,'NextPlot','replacechildren'); Dt=0.1; %sampling period in secs k=1; hp1=text(both(k,1),both(k,2),both(k,3),'thumb'); %get handle to dot object hold on; hp2=text(both(k,4),both(k,5),both(k,6),'index'); hp3=text(both(k,7),both(k,8),both(k,9),'middle'); hp4=text(both(k,10),both(k,11),both(k,12),'ring'); hp5=text(both(k,13),both(k,14),both(k,15),'pinky'); hp6=text(both(k,16),both(k,17),both(k,18),'HAND'); L1=plot3([both(k,1),both(k,16)],[both(k,2),both(k,17)],[both(k,3),both(k,18)]); L2=plot3([both(k,4),both(k,16)],[both(k,5),both(k,17)],[both(k,6),both(k,18)]); L3=plot3([both(k,7),both(k,16)],[both(k,8),both(k,17)],[both(k,9),both(k,18)]); L4=plot3([both(k,10),both(k,16)],[both(k,11),both(k,17)],[both(k,12),both(k,18)]); L5=plot3([both(k,13),both(k,16)],[both(k,14),both(k,17)],[both(k,15),both(k,18)]); hold off; t1=timer('TimerFcn','k=doPlot(hp1,hp2,hp3,hp4,hp5,hp6,L1,L2,L3,L4,L5,both,t1,k)','Period', Dt,'ExecutionMode','fixedRate'); start(t1); end And the doplot function used: function k=doPlot(hp1,hp2,hp3,hp4,hp5,hp6,L1,L2,L3,L4,L5,pos,t1,k) k=k+1; if k<5000%length(pos) set(hp1,'pos',[pos(k,1),pos(k,2),pos(k,3)]); axis([0 255 0 255 0 255]); set(hp2,'pos',[pos(k,4),pos(k,5),pos(k,6)]); set(hp3,'pos',[pos(k,7),pos(k,8),pos(k,9)]); set(hp4,'pos',[pos(k,10),pos(k,11),pos(k,12)]); set(hp5,'pos',[pos(k,13),pos(k,14),pos(k,15)]); set(hp6,'pos',[pos(k,16),pos(k,17),pos(k,18)]); set(L1,'XData',[pos(k,1),pos(k,16)],'YData',[pos(k,2),pos(k,17)],'ZData',[pos(k,3),pos(k,18)]); set(L2,'XData',[pos(k,4),pos(k,16)],'YData',[pos(k,5),pos(k,17)],'ZData',[pos(k,6),pos(k,18)]); set(L3,'XData',[pos(k,7),pos(k,16)],'YData',[pos(k,8),pos(k,17)],'ZData',[pos(k,9),pos(k,18)]); set(L4,'XData',[pos(k,10),pos(k,16)],'YData',[pos(k,11),pos(k,17)],'ZData',[pos(k,12),pos(k,18)]); set(L5,'XData',[pos(k,13),pos(k,16)],'YData',[pos(k,14),pos(k,17)],'ZData',[pos(k,15),pos(k,18)]); else k=1; set(hp1,'pos',[pos(k,1),pos(k,2),pos(k,3)]); axis([0 255 0 255 0 255]); set(hp2,'pos',[pos(k,4),pos(k,5),pos(k,6)]); set(hp3,'pos',[pos(k,7),pos(k,8),pos(k,9)]); set(hp4,'pos',[pos(k,10),pos(k,11),pos(k,12)]); set(hp5,'pos',[pos(k,13),pos(k,14),pos(k,15)]); set(hp6,'pos',[pos(k,16),pos(k,17),pos(k,18)]); end However, when I run handFig('fileName.csv'), I obtain the same error everytime: ??? Error while evaluating TimerFcn for timer 'timer-7' Invalid handle object. I figured that it might come from the function trying to create a new 'csv' and 'both' everytime, so I tried removing them, and feeding the function the data directly, without results. What is exactly the problem? Is there a solution? Thanks a lot!
I think it's because when you call doPlot in the timer for the first time, you pass in t1 as an argument, and it might not exist the first time. Does doPlot need t1 at all? I'd suggest modifying it so it's not used, and then your call to: t1=timer('TimerFcn','k=doPlot(hp1,hp2,hp3,hp4,hp5,hp6,L1,L2,L3,L4,L5,both,k)','Period', Dt,'ExecutionMode','fixedRate'); Note the missing t1 in the doPlot call. Either that, or initialise your t1 before you create the timer so it has some value to pass in. Update (as an aside, can you use pause(Dct) in a loop instead? seems easier) Actually, now I think it's a problem of scope. It took a bit of digging to get to this, but looking at the Matlab documentation for function callbacks, it says: When MATLAB evaluates function handles, the same variables are in scope as when the function handle was created. (In contrast, callbacks specified as strings are evaluated in the base workspace.) You currently give your TimerFcn argument as a string, so k=doPlot(...) is evaluated in the base workspace. If you were to go to the matlab prompt, run handFig, and then type h1, you'd get an error because h1 is not available in the global workspace -- it's hidden inside handFig. That's the problem you're running into. However, the workaround is to specify your function as a function handle rather than a string (it says function handles are evaluated in the scope in which they are created, ie within handFig). Function handles to TimerFcn have to have two arguments obj and event (see Creating Callback Functions). Also, that help file says you have to put doPlot in its own m-file to have it not evaluate in the base Matlab workspace. In addition to these two required input arguments, your callback function can accept application-specific arguments. To receive these input arguments, you must use a cell array when specifying the name of the function as the value of a callback property. For more information, see Specifying the Value of Callback Function Properties. It goes through an example of what you have to do to get this working. Something like: % create timer t = timer('Period', Dt,'ExecutionMode','fixedRate'); % attach `k` to t so it can be accessed within doPlot set(t,'UserData',k); % specify TimerFcn and its extra arguments: t.TimerFcn = { #doPlot, hp1, hp2, hp3, ...., both }; start(t) Note -- the reason k is set in UserData is because it needs to be somehow saved and modified between calls to doPlot. Then modify your doPlot to have two arguments at the beginning (which aren't used), and not accept the k argument. To extract k you do get(timer_obj,'UserData') from within doPlot: function k=doPlot(timer_obj, event, hp1,hp2,hp3,.....) k = get(timer_obj,'UserData'); .... % rest of code here. % save back k so it's changed for next time! set(timer_obj,'UserData',k); I think that's on the right track - play around with it. I'd highly recommend the mathworks forums for this sort of thing too, those people are whizzes. This thread from the mathworks forum was what got me started and might prove helpful to you. Good luck!
Lua "require" with global "local"?
Clearly I have some mixed up, but I figured that by using something like this in "main.lua": local module = require("module") local var = "I should be global?" printthis() with module.lua containing something like: function printthis() print(var) end that printthis(var) would work fine, because now the module.lua code is inside main.lua, no? Instead, printthis has no idea what var is. I read it's good practice to use "local" on Lua variables when possible, but in this case, do I have to make var global or is there a way for module.lua's printthis() function to read var properly?
No. That's not at all how it works. The Lua interpreter provides one global table, referred to as _G normally, unless you're doing something kinky. function printthis() print(var) end This translates to, in reality _G.printthis = function() _G.print(_G.var); end And your code in main is equal to local module = _G.require("module") local var = "I should be global?" _G.printthis() But when you call printthis- where did _G.var get set? Nowhere. So the variable is nil, like all other accesses to a table where there is nothing at that key. It might be inconvenient, but it's a much better idea in the long run to pass arguments than to set global variables instead. Once you come to change anything about the program, it's going to be completely impossible to make any changes, as the logic has no structure and you have no idea what happens where without reading every single line of code and understanding it at once. In addition, you can only use each key in one place, because it's a global table- so I sure hope nobody else wanted to use "var" as a variable name and you don't mind your code silently failing because you got a global name wrong.
The other two answers gloss over an important thing: lexical scoping. This means, roughly, that code can access local variables that are defined where the code is defined. That probably sounds vague, so I'll give an example: local cheese = 'sandwich' print(cheese) -- prints sandwich do -- this begins an anonymous block local cheese = 22 print(cheese) -- prints 22 end print(cheese) -- prints sandwich So what we have here is two different variables: the outer one is "shadowed" by the inner one. Now, onto functions: do local hotdog = 'hot' function nonsense() print(hotdog) end end print(hotdog) -- prints nil, since there is no variable called hotdog here nonsense() -- prints hot Functions can see the local variables from where they are defined, not from where they are called. This is very important and very useful, once you get the hang of it.
I'm no expert in lua, but shouldn't var be passed as variable. Something like this: function printthis(var) print(var) end You're missing your var in function header. And you're passing your var in main.lua as an argument to printthis() function.
Accessing the Body of a Function with Lua
I'm going back to the basics here but in Lua, you can define a table like so: myTable = {} myTable [1] = 12 Printing the table reference itself brings back a pointer to it. To access its elements you need to specify an index (i.e. exactly like you would an array) print(myTable ) --prints pointer print(myTable[1]) --prints 12 Now functions are a different story. You can define and print a function like so: myFunc = function() local x = 14 end --Defined function print(myFunc) --Printed pointer to function Is there a way to access the body of a defined function. I am trying to put together a small code visualizer and would like to 'seed' a given function with special functions/variables to allow a visualizer to 'hook' itself into the code, I would need to be able to redefine the function either from a variable or a string.
There is no way to get access to body source code of given function in plain Lua. Source code is thrown away after compilation to byte-code. Note BTW that function may be defined in run-time with loadstring-like facility. Partial solutions are possible — depending on what you actually want to achieve. You may get source code position from the debug library — if debug library is enabled and debug symbols are not stripped from the bytecode. After that you may load actual source file and extract code from there. You may decorate functions you're interested in manually with required metadata. Note that functions in Lua are valid table keys, so you may create a function-to-metadata table. You would want to make this table weak-keyed, so it would not prevent functions from being collected by GC. If you would need a solution for analyzing Lua code, take a look at Metalua.
Check out Lua Introspective Facilities in the debugging library. The main introspective function in the debug library is the debug.getinfo function. Its first parameter may be a function or a stack level. When you call debug.getinfo(foo) for some function foo, you get a table with some data about that function. The table may have the following fields: The field you would want is func I think.
Using the debug library is your only bet. Using that, you can get either the string (if the function is defined in a chunk that was loaded with 'loadstring') or the name of the file in which the function was defined; together with the line-numbers at which the function definition starts and ends. See the documentation. Here at my current job we have patched Lua so that it even gives you the column numbers for the start and end of the function, so you can get the function source using that. The patch is not very difficult to reproduce, but I don't think I'll be allowed to post it here :-(
You could accomplish this by creating an environment for each function (see setfenv) and using global (versus local) variables. Variables created in the function would then appear in the environment table after the function is executed. env = {} myFunc = function() x = 14 end setfenv(myFunc, env) myFunc() print(myFunc) -- prints pointer print(env.x) -- prints 14 Alternatively, you could make use of the Debug Library: > myFunc = function() local x = 14 ; debug.debug() end > myFunc() > lua_debug> _, x = debug.getlocal(3, 1) > lua_debug> print(x) -- prints 14 It would probably be more useful to you to retrieve the local variables with a hook function instead of explicitly entering debug mode (i.e. adding the debug.debug() call) There is also a Debug Interface in the Lua C API.