-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
throw and catch with SkipMacroException
#11658
Comments
I don't quite agree. We use exceptions for control flow. That's contrived, but valid. People do this in languages with exceptions, it's unrelated to Ruby's throw/catch. An alternative to using exceptions is requiring that skip file happens as the first node in the file. I think that kind of makes sense because skip_file means "skip the entire file" so having it in the middle of the file is awkward. So we could check if the first node is a macro node, and check if it contains a call to skip_file. If so, we evaluate that. Otherwise, we use regular file evaluation and if we find a skip_file we give a compile error saying that skip_file must happen in the beginning of the file. |
Yet another alternative is to deprecate skip_file and stop using it. You can achieve the same thing by not requiring a file. |
Here are the files that use
The most compelling use case seems to be excluding files from a glob via |
I also wonder whether anyone outside this repo is using skip_file. My guess is no, because we use it for platform-de pendent code. In that case, we could refactor our code to not use skip_file and then silently remove that macro method. |
A quick search shows that it is indeed used: {% unless flag?(:anyolite_implementation_ruby_3) %}
{% skip_file %}
{% end %}
# ... {% skip_file if Avram::Model.all_subclasses
.map(&.stringify)
.includes?("UserOptions")
%}
{% skip_file unless Lucille::JSON.includers
.map(&.stringify)
.includes?("UserSettings")
%}
# ... # ...
{% skip_file if @top_level.has_constant? "Spec" %}
# ... |
I'm not sure it would be such a great idea to require Also I think it shouldn't be too difficult to handle later in the file. |
Sounds good. Also note that for example autocasting of numbers/literals is done using exceptions. I think it's just simpler to spend that effort implementing exceptions on the targets we want to port the language to. |
I'm going back and forth on this and my current opinion is that exceptions is a feature of the language like any other and the compiler shouldn't be restricted from using it. Targets that don't support exceptions won't have a native compiler for them and will have to live with cross compilation until they support the full language. It doesn't stop programs being compiled for said target. If this is changed then it should be based on code clarity or performance on the grounds that exceptions should not be used for normal control flow. That said, I don't have a problem with exceptions being used for control flow. |
The compiler uses another exception type, We could probably do the same for This again raises the question whether we should generalize the concept of control flow via stack unwinding. |
This is a follow-up on #15002 which explicitly assigns a dummy callstack to `RetryLookupWithLiterals` for performance reasons. `CallStack.empty` is intended to make this use case a bit more ergonomical. It doesn't require allocating a dummy instance with fake data. Instead, it's an explicitly empty callstack. This makes this mechanism easier to re-use in other places (ref #11658 (comment)).
SkipMacroException
is used in the to signal askip_file
macro expression. This is not actually an error. The exception is used to work likethrow
/catch
in Ruby.We don't have
throw
/catch
in Crystal and I think it's for good reasons (https://forum.crystal-lang.org/t/throw-and-catch/256). Yet we make use of this concept in the compiler. That's definitely a hack because there's no error involved, but it necessarily inherits fromException
which is the base error type.A side effect of that is that the compiler requires exceptions to function, not just for error handling. This poses difficulties when porting the compiler to new targets where exception support is still missing (#10870 (comment)).
I think the right solution would be to remove
SkipMacroException
and properly implementskip_file
with an other form of signalling that is embedded in regular code flow. This is probably not going to be trivial because it needs to be handled through several levels of compiler layers.Alternatively, we could decide this might actually be a good use case for this pattern and we want to keep it. Then we should make sure that it's properly implemented (non-error exception base type, skip the stack trace). Maybe this could also warrant adding
throw
/catch
feature to the language.The text was updated successfully, but these errors were encountered: