Skip to content

Introduce try/catch control structure #152

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

Merged
merged 8 commits into from
Jun 30, 2020

Conversation

sauerbraten
Copy link
Collaborator

@sauerbraten sauerbraten commented Jun 23, 2020

{{try}} .. {{end}} or {{try}} .. {{catch [err]}} .. {{end}} executes a list of statements, recovering from any panic (runtime errors) inside. When using try with catch, the statement list inside catch/end is executed in the event of a recovery.

catch takes an optional identifier name under which the error will be available inside the catch statement list.

In case of no runtime error, the output generated by the try statement list will be kept. In case of any panic, no output from the try statement list will be kept.

Born out of the ashes of #151.

try/end or try/recover/end execute a list of statements, recovering from any panic (runtime errors) inside. when using try with recover, the statement list inside recover/end is executed in the event of a recovery.

recover takes an optional identifier name under which the error will be available inside the recover statement list.

in case of no runtime error, the output generated by the try statement list will be kept. in case of any panic, no output from the try statement list will be kept.
@sauerbraten sauerbraten mentioned this pull request Jun 23, 2020
@tooolbox
Copy link
Contributor

Brilliant! (I didn't deep-dive into the internals to review what you did but the concept is great.)

Do you think it will affect performance much? Probably only if you're dealing with tons of panics, I imagine.

@sauerbraten
Copy link
Collaborator Author

sauerbraten commented Jun 24, 2020

Do you think it will affect performance much?

Well it only impacts performance when you actually use it. If you use it, there's certainly a hit to the speed of outputting rendered results and an increase in memory consumption, because we buffer output until the entire block was executed. Other than that, it shouldn't have a big impact, it only shuffles around a few variables before and after executing the statement list. Deferred functions don't have any significant overhead in recent Go versions, either, so the panic handling should be ok, too.

@sauerbraten
Copy link
Collaborator Author

I liked the suggestion to rename "recover" to "catch" you had here: #151 (comment). Coming up!

@sauerbraten sauerbraten changed the title Introduce try/recover control structure Introduce try/catch control structure Jun 24, 2020
@tooolbox
Copy link
Contributor

Well it only impacts performance when you actually use it. If you use it, there's certainly a hit to the speed of outputting rendered results and an increase in memory consumption, because we buffer output until the entire block was executed. Other than that, it shouldn't have a big impact, it only shuffles around a few variables before and after executing the statement list. Deferred functions don't have any significant overhead in recent Go versions, either, so the panic handling should be ok, too.

That makes sense. Yeah, it's something you can use if you need it.

I liked the suggestion to rename "recover" to "catch" you had here: #151 (comment). Coming up!

👍 I think this is great, a good tool for the arsenal :)

I broke this in 2e37ce4, forgetting it's an exported function
…e() which was exported via Set()

if setValue() couldn't find a variable with the given name in any of the scopes, it would create the variable in the top-most one instead of the current one. 6e9c5b9 fixed this, but outside code might depend on this bug to set global variables via Set(), so SetGlobal() can now be used to do that.
to ensure it's still possible to create new vars via the Runtime API, there's a new Let() method (which might shadow a var existing in a parent scope), as well as SetOrLet() which does the right thing for you, depending on if a var with the given name exists or not.
@sauerbraten sauerbraten merged commit e7d886a into CloudyKit:master Jun 30, 2020
@sauerbraten sauerbraten deleted the try-recover branch June 30, 2020 08:46
@tooolbox
Copy link
Contributor

Sweet! 🎉

Are you going to tag v3.0.1? :)

@sauerbraten
Copy link
Collaborator Author

Very likely will tag v4.0.0 soon, there are breaking API changes once again... 🤷‍♂️

@tooolbox
Copy link
Contributor

tooolbox commented Jul 1, 2020

Huh, kk, I mean this is not breaking right, it's additive? Would it make sense to tag it before you do the major version jump?

@sauerbraten
Copy link
Collaborator Author

A change to runtime.Set() is kinda breaking, see

@tooolbox
Copy link
Contributor

tooolbox commented Jul 1, 2020

Huh, hadn't noticed that earlier. Yeah, makes sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants