Page 1 of 1

Parsing string to math (loadstring)

Posted: Thu Nov 20, 2014 1:14 pm
by PartyCow
Hello.

I'm making a program/game that needs to convert a string input (mathematical function, ex. sin(x)+2).
Looking around I found the function eval, which converts string to function. This found to be exsistent in lua aswell named loadstring.
Although trying to run code, it doesn't convert string to math properly.

Code

Code: Select all

 o = 0
 cmd = loadstring("o = sin(4)")
 love.window.setTitle(o)
Sets the title to 0 rather than whateverthehell sin(4) is.

Help appcreiated.

Thanks

Re: Parsing string to math (loadstring)

Posted: Thu Nov 20, 2014 1:59 pm
by zorg
I think you want this (untested, sorry):

Code: Select all

o = 0
cmd = loadstring("o = sin(4)") -- returns a _function_
cmd() -- call that function
love.window.setTitle(o)
or even better:

Code: Select all

f = "sin(4)"
love.window.setTitle(loadstring("return " .. f)) -- put a () after f) to actually call the loaded string
though not if you want to set it every frame... that would probably be "slow as hell".

Re: Parsing string to math (loadstring)

Posted: Thu Nov 20, 2014 8:57 pm
by PartyCow
zorg wrote:I think you want this (untested, sorry):

Code: Select all

o = 0
cmd = loadstring("o = sin(4)") -- returns a _function_
cmd() -- call that function
love.window.setTitle(o)
or even better:

Code: Select all

f = "sin(4)"
love.window.setTitle(loadstring("return " .. f))
though not if you want to set it every frame... that would probably be "slow as hell".
Works, thanks.
I now realize I managed to oversee it whoops.

Re: Parsing string to math (loadstring)

Posted: Fri Nov 21, 2014 2:22 am
by Positive07
zorg wrote:I think you want this (untested, sorry):

Code: Select all

o = 0
cmd = loadstring("o = sin(4)") -- returns a _function_
cmd() -- call that function
love.window.setTitle(o)
or even better:

Code: Select all

f = "sin(4)"
love.window.setTitle(loadstring("return " .. f))
though not if you want to set it every frame... that would probably be "slow as hell".
You said something in the first code but didnt do it in the second one haha

Code: Select all

f = "sin(4)"
love.window.setTitle(loadstring("return " .. f)())
Also if the text comes from user input then you should do a couple of things:
  • If there is an error in the code the user wrote, then it shouldn't spread to your code, or else your game will crash, to do this you can use pcall:

    Code: Select all

    userinput = "math.sin(4); return 'a'"
    func = loadstring(userinput)
    ok,msg = pcall(func) --This call func, and returns true if there was no error or false if there was
    if ok then --The code ran fine
        if msg then 
            print(msg) --Prints "a"
        end
    else --Oops it crashed
        print(msg) --ERROR Bla bla bla
    end
    
  • You dont want the user to execute dangerous code, for example if the user inputs:

    Code: Select all

    love = nil
    Then your game wont act properly at all. To maintain the user away from your functions you can use setfenv:

    Code: Select all

    env = {math = math, string = string}
    userinput = "love = {graphics = "a"}"
    func = loadstring(userinput)
    ok,msg = pcall(func)
    print(love.graphics)--table 0x....
    if ok then
        if msg then 
            print(env.love.graphics) --Prints "a"
        end
    else
        print(msg)
    end
    
    NOTE: If you want the user to use a function you have, then you should put it in the environment as I did above with math and string but this could be dangerous too, since you are just referencing a table, then if the user did this

    Code: Select all

    math.floor = function () return 200 end
    math.floor wont do what you expect it to do, to allow the user to use math.floor while not allowing to change the behavior of YOURS math.floor you have to deep copy the math table

    Code: Select all

    env = {math = deepcopy(math), string = deepcopy(string)}
    There are many deepcopy scripts here in the forum (Robin made an amazing one) so make a search and you'll find one
EDIT:
zorg wrote:Though you did make a minor typographical mistake: wrote "loadsting" instead of loadstring in one of your code blocks.
Thanks zorg, fixed the error

Re: Parsing string to math (loadstring)

Posted: Fri Nov 21, 2014 5:26 am
by zorg
Positive07 wrote:-snip-
Haha, you're right, i did forgot the (), my bad! :3
Though you did make a minor typographical mistake: wrote "loadsting" instead of loadstring in one of your code blocks.