Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom error handler #11634

Closed
appgurueu opened this issue Sep 16, 2021 · 4 comments · Fixed by #11913
Closed

Custom error handler #11634

appgurueu opened this issue Sep 16, 2021 · 4 comments · Fixed by #11913
Labels
Feature request Issues that request the addition or enhancement of a feature @ Script API

Comments

@appgurueu
Copy link
Contributor

Lua's error handling can be frustrating; while you can throw table errors, nowhere is it done, and Lua errors are just serialized as they are thrown - you can't distinguish a syntax error from a stack overflow without pattern matching - and if the error goes all the way up, neither Minetest nor Lua will dump it for you.

I wish there was some kind of top-level custom error handler like https://lovr.org/docs/lovr.errhand. First of all, that could take care of the serialization of non-string errors, and second, it would also enable correct error messages if a preprocessor is used, pointing the user to the actual source line by mapping generated source lines to actual sources.

@appgurueu appgurueu added the Feature request Issues that request the addition or enhancement of a feature label Sep 16, 2021
@SmallJoker
Copy link
Member

Would you have some concrete examples? Lua errors can be captured with pcall/xpcall. For which use-case do you need more precise error messages? Or is the issue about missing type checks on C++ side?

@appgurueu
Copy link
Contributor Author

appgurueu commented Sep 26, 2021

Would you have some concrete examples? Lua errors can be captured with pcall/xpcall. For which use-case do you need more precise error messages? Or is the issue about missing type checks on C++ side?

I need data errors, for instance error{type = "numeric", message = "..."} so that I can actually catch errors. If such an error bubbles up though, you will just get (error message is a table object) or the like which is pretty useless, forcing you to choose between useful errors and catchable errors (this could be regarded as a Lua flaw, but as usual, Lua provides the necessary mechanisms to build something useful).

Lua errors can be captured with pcall/xpcall

I know, but this only applies to the code I write, and even then it would be quite a hassle to have preprocessor wrap every function call as an [x]pcall. Engine calls (such as running callbacks) can't be wrapped at all and would require even more dirty hacks (such as wrapper functions).

My precise usecase is that I am planning on writing a Lua preprocessor ("Mond"). I don't want to lose useful error messages though (as Moonscript partially does). I see two options for this:

  1. Generate Lua sources which are very similar and have the same line numbers: Line number in error message matches, quite useful, and I will support this;
  2. Translate Lua errors into Mond errors

The latter needs an error handler (and a lookup table for generated Lua code -> Mond code). Note that I want Mond to have a feature where it splits operations across multiple lines for more accurate error messages:

print(a + b + c)

becomes

print(a
+b
+c)

That way, the error line provided by Lua (1, 2 or 3) can be turned into an exact error location in Mond (first, second or third addition).

@appgurueu
Copy link
Contributor Author

appgurueu commented Dec 16, 2021

Alright, I found my hack around it:

_dbg = {}
_dbg._proxy = newproxy(true)
getmetatable(_dbg._proxy).__gc = function()
	minetest.log("error message substitute!")
end
error("error time!")

works if modsec is disabled, which will probably be the case in a debug environment.

@appgurueu
Copy link
Contributor Author

In Löve, the following is possible:

function love.errorhandler(msg)
	print("error:", msg)
	local index = 1
	while true do
		local name, value = debug.getlocal(4, index)
		if not name then break end
		print("local", name, "=", value)
		index = index + 1
	end
end

function love.draw()
	local str = 'Hello World!'
	error"hello matrix"
    love.graphics.print(str, 400, 300)
end

which will print

$ love errorhandler
error:	main.lua:14: hello matrix
local	str	=	Hello World!

if executed - that is, it is possible to catch an error and inspect the current state of the program at the time of the error. If paired with my dbg mod, this would finally allow for a pleasant debugging experience.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature request Issues that request the addition or enhancement of a feature @ Script API
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants