Parsing string to math (loadstring)

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
PartyCow
Prole
Posts: 18
Joined: Sat Nov 17, 2012 3:12 pm

Parsing string to math (loadstring)

Post 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
User avatar
zorg
Party member
Posts: 3468
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Parsing string to math (loadstring)

Post 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".
Last edited by zorg on Fri Nov 21, 2014 5:27 am, edited 1 time in total.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
PartyCow
Prole
Posts: 18
Joined: Sat Nov 17, 2012 3:12 pm

Re: Parsing string to math (loadstring)

Post 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.
User avatar
Positive07
Party member
Posts: 1014
Joined: Sun Aug 12, 2012 4:34 pm
Location: Argentina

Re: Parsing string to math (loadstring)

Post 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
Last edited by Positive07 on Fri Nov 21, 2014 3:31 pm, edited 1 time in total.
for i, person in ipairs(everybody) do
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
User avatar
zorg
Party member
Posts: 3468
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Parsing string to math (loadstring)

Post 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.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 1 guest