## [SOLVED] Handling error exceptions for assert(loadstring(str))() ?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
unixfreak
Citizen
Posts: 77
Joined: Thu Oct 15, 2015 6:25 am
Location: Bristol, UK
Contact:

### [SOLVED] Handling error exceptions for assert(loadstring(str))() ?

I am trying to add scriptable lua to a console as part of a game, for example to change variables quickly or run custom lua code to edit levels etc.

I have figured out i can use something like this:

Code: Select all

local out = assert(loadstring(console.command))()
Where the console uses text input to supply the console.command variable. Eg; User types some lua code into the console, when they press return, the above code line will execute.

This allows me to enter commands directly into the game whilst it is running, such as:

Code: Select all

world.gravity = 2300
Where world.gravity is a variable within the actual love2d project.
And also to help modify levels very fast, being able to type actual lua code, for example;

Code: Select all

for _, e in (world.enemies) do editor:remove(e) end
Essentially this is being run as;

Code: Select all

assert(loadstring("world.gravity = 2300"))()
This works fine, however, if there is a syntax error... the entire love2d application crashes to the blue error screen. How can i stop this from happening so i can instead print "error" to the console instead of crashing the entire program?

For context; This is what i am trying to achieve; https://i.imgur.com/mEfBQYn.jpg The lines which start with DEBUG are the commands that were entered into the in-game console. Here's the project/file which i've added this to: https://github.com/Jigoku/boxclip/blob/ ... e.lua#L115

The problem is that i cannot find a way to stop the game crashing if invalid syntax is entered. Does anyone know if there is a way to do this?
Last edited by unixfreak on Tue Aug 14, 2018 9:55 pm, edited 3 times in total.

pgimeno
Party member
Posts: 1937
Joined: Sun Oct 18, 2015 2:58 pm
Location: Valencia, ES

### Re: Handling error exceptions for assert(loadstring(str))() ?

Looks like a job for pcall.

unixfreak
Citizen
Posts: 77
Joined: Thu Oct 15, 2015 6:25 am
Location: Bristol, UK
Contact:

### Re: Handling error exceptions for assert(loadstring(str))() ?

pgimeno wrote:
Tue Aug 14, 2018 9:19 pm
Looks like a job for pcall.
Hi, thanks for replying. I previously looked up that function, but can't understand how i would use it here.
How would i go about using pcall for this snippet?

Code: Select all

local out = assert(loadstring(console.command))()
console:print(out)
I have tried something such as:

Code: Select all

local out = pcall(assert(loadstring(console.command))())

if out then
console:print(out)
else
console:print("ERROR: invalid syntax!")
end

But i get:

Code: Select all

Error: console.lua:115: bad argument #1 to 'pcall' (value expected)
stack traceback:
[string "boot.lua"]:637: in function <[string "boot.lua"]:633>
[C]: in function 'pcall'
console.lua:115: in function 'keypressed'
input.lua:35: in function <input.lua:31>
[string "boot.lua"]:503: in function <[string "boot.lua"]:493>
[C]: in function 'xpcall'


unixfreak
Citizen
Posts: 77
Joined: Thu Oct 15, 2015 6:25 am
Location: Bristol, UK
Contact:

### Re: Handling error exceptions for assert(loadstring(str))() ?

Oh nevermind, i just got this working;

Code: Select all

local out = pcall(function() assert(loadstring(console.command))() end)

if out then
console:print(out)
else
console:print("ERROR: invalid lua snytax!")
end

This works!
Thanks for reminding me of pcall, i gave up the other day trying to solve this, but misunderstood how to use it properly.

Solved i guess, thanks.

pgimeno
Party member
Posts: 1937
Joined: Sun Oct 18, 2015 2:58 pm
Location: Valencia, ES

### Re: Handling error exceptions for assert(loadstring(str))() ?

You probably don't want to use assert, as that would need more layers of error handling. Try this:

Code: Select all

local fn, err = loadstring(console.command)
if not fn then
console:print(err)
else
local ok, result = pcall(fn)
if not ok then
-- There was an error, so result is an error. Print it out.
console:print(result)
elseif result then
console:print(result)
end
end

Before submitting I saw your post. That creates one extra function on the fly. I just discussed in another thread why that's best avoided, and the above method does just that. You can't avoid creating the function with the user code, but you can avoid creating the anonymous wrapper function around assert().

unixfreak
Citizen
Posts: 77
Joined: Thu Oct 15, 2015 6:25 am
Location: Bristol, UK
Contact:

### Re: Handling error exceptions for assert(loadstring(str))() ?

By the way, i posted to soon about this being solved, whilst it didn't crash on invalid syntax, it did crash when the syntax was valid (something about expecting string/boolean error).

pgimeno wrote:
Tue Aug 14, 2018 9:48 pm
You probably don't want to use assert, as that would need more layers of error handling. Try this:

Code: Select all

local fn, err = loadstring(console.command)
if not fn then
console:print(err)
else
local ok, result = pcall(fn)
if not ok then
-- There was an error, so result is an error. Print it out.
console:print(result)
elseif result then
console:print(result)
end
end

Before submitting I saw your post. That creates one extra function on the fly. I just discussed in another thread why that's best avoided, and the above method does just that. You can't avoid creating the function with the user code, but you can avoid creating the anonymous wrapper function around assert().
I just tried your snippet, and that works perfectly, along with the extra information that shows the actual error message you would get from lua on the command line, which is a huge bonus. https://i.imgur.com/Ed3NmTs.png

Many thanks!

pgimeno
Party member
Posts: 1937
Joined: Sun Oct 18, 2015 2:58 pm
Location: Valencia, ES

### Re: [SOLVED] Handling error exceptions for assert(loadstring(str))() ?

Yeah, you missed returning the value for pcall: pcall(function() return assert(...

Edit: also, you missed the second argument, now that I look closer. The first argument is always a boolean. That was probably the problem.

unixfreak
Citizen
Posts: 77
Joined: Thu Oct 15, 2015 6:25 am
Location: Bristol, UK
Contact:

### Re: [SOLVED] Handling error exceptions for assert(loadstring(str))() ?

pgimeno wrote:
Tue Aug 14, 2018 9:59 pm
Yeah, you missed returning the value for pcall: pcall(function() return assert(...

Edit: also, you missed the second argument, now that I look closer. The first argument is always a boolean. That was probably the problem.
Yeah, looking at that now, i see that is the case. Can't thank you enough for a solution. Cheers.

pgimeno
Party member
Posts: 1937
Joined: Sun Oct 18, 2015 2:58 pm
Location: Valencia, ES

### Re: [SOLVED] Handling error exceptions for assert(loadstring(str))() ?

You're welcome. Now that I think about it, I've realized that that's only half-baked, as it only deals with one return value, without even distinguishing nil from false or from no value. In the console of Lua and LuaJIT that works perfectly:

Code: Select all

> return nil
nil
> return
> return false
false
> return 1, 2
1	2

A more complete solution that behaves more like the Lua console would be like this:

Code: Select all

local fn, err = loadstring(console.command)
if not fn then
console:print(err)
else
local result = {pcall(fn)}
local ok = table.remove(result, 1)
if not ok then
console:print(result[1])
else
for i = 1, #result do
result[i] = tostring(result[i])
end
console:print(table.concat(result, '\t')) -- well, tab handling isn't perfect in graphics mode but it does something
end
end

(Disclaimer: not tested). Unfortunately that generates quite some single-use objects, but well. Of course, you can always just omit printing the return value and call it a day. Or for extra functionality, you could replace tostring() with inspect() to help debugging (after requiring inspect.lua)

### Who is online

Users browsing this forum: Google [Bot], Nelvin and 9 guests