This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Molinko's profile picture

identifying functions and serialization

Started by Molinko, 30 January 2014 - 02:09 PM
Molinko #1
Posted 30 January 2014 - 03:09 PM
[indent=1]Hello all! I have a few questions about functions and i guess the 'lua environment' ..

1.) Is it possible to get the string name of a local function from the running program?? example..
 I'm executing a program called 'myProgram',
	local function a()
	  -- do stuff
	end

	local function b()
	  -- print( getFunctionName(a) ) -- <-- is this possable?? or will i allways get "function(address#)" Keep in mind it wont be in _G table cause its local to the program..
	end

2.) How can i get the plain text of a function and not just a function value?? example
lets say i have a client and host connected.. The host asks the client to call a function on its local self that it doesnt have, so the client replys along the lines
of 'I dont know wtf that function is…'. Is it possable for the host to get the definition of a local function with its string name, so i can send it over rednet and loadstring it??
Keep in mind the function will be local to the host executing the file and will not be in _G

So basically I just want to be able to pull a function definition and assigned name from a currently running local environment… Is this possable?? If not, could you suggest a way to
serialize functions or point me in the right direction?? I realize there are a few apis for serializing functions, but i didnt understand them very well..

Thank you in advance for any help. -Mo[/indent]
CometWolf #2
Posted 30 January 2014 - 03:29 PM
In order to get a function's name, wouldn't you need to know the name in the first place? Otherwise how would the code know what function you want the name of?

As for your other problem, idk how to properly do it, but storing the functions as strings in a table which you could send over rednet and then loadstringing it would work, no?
Lyqyd #3
Posted 30 January 2014 - 06:12 PM
The things you're asking to do are sort of possible, but the better question is, what are you actually trying to accomplish? There's probably an easier way to arrive at whatever your end goal is than this route.
Molinko #4
Posted 30 January 2014 - 06:35 PM
The things you're asking to do are sort of possible, but the better question is, what are you actually trying to accomplish? There's probably an easier way to arrive at whatever your end goal is than this route.

example:
I have 2 computers, 1 master 1 slave.
The slave is running and listening for modem messages. Some of these messages are string functions to be executed on the slave.
Lets say i want to send a function to the slave from the master but the function is in the masters local environment not in an API..
What i want to do is something along the lines of …

-- MASTER
local A = function() print("doing A stuff...") end
-- call a magical function ?? THIS is what I'm REALLY after...
funcName,funcBody = functionToString( A ) <-- HERE
-- funcName and funcBody should be strings... 'A', 'print("doing A stuff...")'
rednet.send( id, textutils.serialize{name=funcName,body=funcBody})
-- SLAVE
local resources = {} -- table of functions we know and recieve from file or rednet...
msg = {rednet.recieve()}
funcObj = textutils.unserialize(msg[2])
local func, err  = loadstring( funcObj.body )
if func then
  resources[funcObj.name] = func
end

Does this make any sense? Is le possible?? ps. this is more pseudocode then full concept..
Lyqyd #5
Posted 30 January 2014 - 07:54 PM
Well, you definitely don't need the "name" of the function to do that. Functions don't even have names, they're just like every other value, and can be stored in any number of variables. You may be able to do stuff with string.dump and loadstring, maybe with some base64 for the transport of it. It's probably not the best thing to do, though.

I'm still kind of curious as to what you're planning on using this to accomplish. What's the actual task you have in mind, not just "I want to send functions to another computer to execute.", but something like, "I want to control one computer from another" or similar?
Molinko #6
Posted 30 January 2014 - 08:05 PM
Well, you definitely don't need the "name" of the function to do that. Functions don't even have names, they're just like every other value, and can be stored in any number of variables. You may be able to do stuff with string.dump and loadstring, maybe with some base64 for the transport of it. It's probably not the best thing to do, though.

I'm still kind of curious as to what you're planning on using this to accomplish. What's the actual task you have in mind, not just "I want to send functions to another computer to execute.", but something like, "I want to control one computer from another" or similar?

I was thinking of a rc turtle when i thought of this case but that got the wheels in my head..
The idea originally was to be able to send a custom algorithm to a turtle on the fly.
I realize the potential for security risks but thats not really a concern of mine at all.
Yevano #7
Posted 30 January 2014 - 09:01 PM
Well, you definitely don't need the "name" of the function to do that. Functions don't even have names, they're just like every other value, and can be stored in any number of variables. You may be able to do stuff with string.dump and loadstring, maybe with some base64 for the transport of it. It's probably not the best thing to do, though.

Let me expand upon that. I've done something similar in a turtle swarm project where a master computer would send functions as instructions to the slave turtles. First, there's a hoop you'll have to jump through to actually do this, and after that you need to remember that all locals which the function referenced previously will be made invalid by calling it in a different environment. What you'd want to do is call string.dump on the function to get its bytecode as a string. However, because of some weirdness with rednet turning chars above 127 into garbage, you'll need to encode this string and decode it at the other end to something rednet won't mess with. A naive solution is to just send two bytes per character. One is a flag telling whether the number is above or below the "garbage" range, and the other is the encoded char, which you just leave as is or add 128 to when decoding. I won't get into details but there are of course way more efficient ways of doing the encoding. At the other side, you need to decode the message to get the actual bytecode. Once you do that, you just load the function with loadstring and call it.
Edited on 30 January 2014 - 08:02 PM
Bomb Bloke #8
Posted 30 January 2014 - 10:28 PM
I was thinking of a rc turtle when i thought of this case but that got the wheels in my head..
The idea originally was to be able to send a custom algorithm to a turtle on the fly.
I realize the potential for security risks but thats not really a concern of mine at all.
This has probably occurred to you, but if you break down the average "make a turtle do a job" function you won't find many unique commands in it - you could construct a table filled with basic strings such as "forward", "turnLeft", "dig", "forward", "repeatLastx5", etc, transmit that, then have the turtle "translate" what it receives into the code which it actually runs.

You could literally create a table which uses such strings as keys, and has the corresponding functions you want to execute attached to them, turtle-side.
surferpup #9
Posted 31 January 2014 - 12:17 AM
Consider the following table:



myTable = {
  function1 = function()
	  print ("function1")
	end
  ,
  function2 = function()
	  print ("function2")
	end
}

I can call these functions from my code like this:

messageReceived = "function1"
myTable[messageReceived]()
messageReceived = "function2"
myTable[messageReceived]()

Does that point you in a direction you are trying to go?

edit: fixed syntax on function call
Edited on 30 January 2014 - 11:19 PM