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

Eval() - running a function based on user input

Started by ThinkInvisible, 16 September 2012 - 12:32 PM
ThinkInvisible #1
Posted 16 September 2012 - 02:32 PM
in the language TorqueScript, the function eval("text"); will run "text" as if it was entered into the program. So 'eval("echo(1+2);");' would be the same as typing 'echo(1+2)' into the program. This is useful because it allows user input to do things as opposed to using a huge If/Else If/Else If/etc. structure.

Is there anything similar to this in Lua?
MysticT #2
Posted 16 September 2012 - 03:37 PM
loadstring
It loads the given string as a function that you can run.
Example:

local func, err = loadstring("print('Hello World!')")
if func then -- check if the function is loaded
  func() -- run the function
else
  print("Error: ", err) -- error loading the string
end
This is how programs are run in CC. The program is read as a string and then loaded with loadstring.
Magus #3
Posted 16 September 2012 - 03:41 PM
the loadstring function can do this

src = "print('hello world')"
loadstring(src)()
ThinkInvisible #4
Posted 16 September 2012 - 05:52 PM
I'm getting 'string:1: attempt to call nil' errors whenever I try to call a function for some reason.


function vclock()
os.reboot()
end
...
loadstring(x .. "()")()
--this always returns the error, even if x is 'vclock'.
MysticT #5
Posted 16 September 2012 - 05:53 PM
Code?
ThinkInvisible #6
Posted 16 September 2012 - 05:57 PM
X is usually being obtained from a series of 'char' events, if that matters at all.
MysticT #7
Posted 16 September 2012 - 06:03 PM
That's because the function doesn't exist in the loaded function's environment. You need to set it's environment using setfenv:

local f = loadstring(x.."()")
if f then
  setfenv(f, _G)
  f()
end
And you could set the environment to a table that only contains your functions, so nothing else can be run:

local myFunctions = {}

function myFunctions.doSomething()
  print("This is in a custom environment.")
end

local f = loadstring("doSomething()")
if f then
  setfenv(f, myFunctions)
  f()
end
ThinkInvisible #8
Posted 16 September 2012 - 06:12 PM
Still giving the same error.


 userin = string.lower(GUI_read(nil, 6)) --GUI_read is a modified version of read() that keeps part of the screen intact. Uses the 'char' event.
 x = "vc" .. userin

local f = loadstring(x .. "()")
if f then
 setfenv(f, _G)
 f()
end
MysticT #9
Posted 16 September 2012 - 06:19 PM
My bad. Try with this:

local f = loadstring(x.."()")
if f then
  setfenv(f, getfenv())
  f()
end
I tested it and it works.
ThinkInvisible #10
Posted 16 September 2012 - 06:48 PM
Thanks.

One last thing - do you know how to convert something returned from a "key" event to a letter?
MysticT #11
Posted 16 September 2012 - 06:59 PM
Use a "char" event instead. Each time you press a key it generates a "key" event, and if it's a character it also generates a "char" event, so you just have to wait for that event after the key.
If you still want to convert it from the "key" event, you can use the keys api (added in CC 1.4).