-
Notifications
You must be signed in to change notification settings - Fork 3
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
ADD error catching #109
base: dev
Are you sure you want to change the base?
ADD error catching #109
Conversation
discard runCatchingTyped( | ||
fun = testErrorProc, | ||
fatal = false, | ||
messagePrefix = "Intentional Error: " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove ": "
@@ -33,9 +36,41 @@ proc getSecondsSinceEpoch* (this: ptr PlaydateSys): tuple[seconds: uint, millise | |||
type PDCallbackFunction* = proc(): int {.raises: [].} | |||
var updateCallback: PDCallbackFunction = nil | |||
|
|||
proc runCatchingTyped*[T](fun: () -> T, fatal: bool = false, messagePrefix: string=""): T = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Nycto
Is there some magic we can add to get rid of the separate typed and untyped variant using a template, macro, or auto
typing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should be able to implement a single version of this by using a template like this:
template runCatching*(fatal: bool = false, messagePrefix: string = "", body: typed): auto =
try:
body
except:
getCurrentException().logException(fatal, messagePrefix)
default(typeof(body))
try: | ||
message = &"{messagePrefix}: {getCurrentExceptionMsg()}\n{exception.getStackTrace()}" | ||
# replace line number notation from (90) to :90, which is more common and can be picked up as source link | ||
message = message.replace('(', ':') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apply this replacement to the stacktrace only
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine either way
if fatal: | ||
playdate.system.error("FATAL:" & getCurrentExceptionMsg()) | ||
|
||
proc runCatchingVoid*(fun: () -> void, fatal: bool = false, messagePrefix: string = "") = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"fun" might not be a very descriptive name for non-Kotlin devs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
body
is the usual name used in Nim
@Nycto This one is a bit rough still, see my comments. I thought I'd first make a PR to see if you'd agree to this idea before polishing it. Note there is also a question for you in there regarding a possibility to have a single proc for both typed and untyped usage. |
proc runCatchingTyped*[T](fun: () -> T, fatal: bool = false, messagePrefix: string=""): T = | ||
try: | ||
return fun() | ||
except: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should pull all of this exception logging code into its own proc, with a signature like this:
proc logException*(exception: ref Exception, fatal: bool = false, messagePrefix: string = "")
let exception = getCurrentException() | ||
var message: string = "" | ||
try: | ||
message = &"{messagePrefix}: {getCurrentExceptionMsg()}\n{exception.getStackTrace()}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use exception.msg
instead of getCurrentExceptionMsg
except: | ||
let exception = getCurrentException() | ||
var message: string = "" | ||
try: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this try/catch?
if fatal: | ||
playdate.system.error("FATAL:" & getCurrentExceptionMsg()) | ||
|
||
proc runCatchingVoid*(fun: () -> void, fatal: bool = false, messagePrefix: string = "") = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
body
is the usual name used in Nim
@@ -33,9 +36,41 @@ proc getSecondsSinceEpoch* (this: ptr PlaydateSys): tuple[seconds: uint, millise | |||
type PDCallbackFunction* = proc(): int {.raises: [].} | |||
var updateCallback: PDCallbackFunction = nil | |||
|
|||
proc runCatchingTyped*[T](fun: () -> T, fatal: bool = false, messagePrefix: string=""): T = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should be able to implement a single version of this by using a template like this:
template runCatching*(fatal: bool = false, messagePrefix: string = "", body: typed): auto =
try:
body
except:
getCurrentException().logException(fatal, messagePrefix)
default(typeof(body))
try: | ||
message = &"{messagePrefix}: {getCurrentExceptionMsg()}\n{exception.getStackTrace()}" | ||
# replace line number notation from (90) to :90, which is more common and can be picked up as source link | ||
message = message.replace('(', ':') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine either way
What is it
A proc that will execute a provided lambda and catch any errors. The exception is printed to the console.
Optionally, the error is marked as fatal, causing the simulator to be paused and the error message to be printed in red.
This is manly intended to add default error catching to the main update loop, but it can also be used in game code if desired. Sample usage is added
Why
Challenges
handler
call in theinitSdk
macro too but that is executed very early in the boot sequence and I couldn't figure that outOut of scope
I plan a follow-up PR where the error is printed to the screen (device only, since simulator has the Console view). This provides a similar crash experience to the lua sdk and allows players to share a photo of the stacktrace with the dev, as is common practice for lua games.