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

Make it possible to define PRE and POST phasers #15

Open
masak opened this issue Feb 19, 2015 · 1 comment
Open

Make it possible to define PRE and POST phasers #15

masak opened this issue Feb 19, 2015 · 1 comment

Comments

@masak
Copy link
Owner

masak commented Feb 19, 2015

This is a curious one, but one I think we should tackle. Very simple macros generate some code and then dump it on the site the macro was called. Any phaser macro typically wouldn't; they need to make sure this code runs at a particular time.

I can think of two approaches to this:

  • Without co-opting the compiler. The macro would have to queue up a request to participate in the construction of the surrounding sub. (So I guess there'd have to be a mechanism for that, or at least a mechanism to override standard sub construction.) As the sub is created, the passed statementlist gets extended with PRE blocks at the beginning and POST blocks at the end.
  • Co-opting the compiler. Same, but instead of forcibly inserting blocks in a statementlist, the Q::Sub has hooks for "before sub body" and "after sub body". In fact, it would be interesting to classify all the existing Perl 6 phasers in this way: what program element do they hook onto, and what's the relationship ("before", "after", etc)?

In both cases, the injected blocks need to be wrapped with the implicit boilerplate of "...make sure the value we get back is truthy, otherwise die with an error message". How this relates to issue 7 and whether blocks should be allowed to return values, I'm not sure. Need to think about that a bit more.

It should be possible to nest PRE and POST phasers inside each other, so that they can share locally defined lexicals.

In fact, PRE and POST probably shouldn't be restricted to just subs; it should probably work in any type of block. That way, one could put them on loops, too. Or on the entire program.

Bonus points for making the error message include the text of the precondition that fails. Like Rakudo does:

$ perl6 -e 'for 1..10 { PRE { $_ < 5 }; say $_ }'
1
2
3
4
Precondition '{ $_ < 5 }' failed

(In fact, can do better in two ways there. Firstly, in the case of a conjunction &&, we could single out the conjunctive term that failed. Rakudo currently does not do this:

$ perl6 -e 'for 1..10 { PRE { $_ < 5 && $_ > 0 }; say $_ }'
1
2
3
4
Precondition '{ $_ < 5 && $_ > 0 }' failed

(Could say Precondition '$_ < 5' failed instead.)

Secondly, we could show the values of all the variables involve in the failing term. That'd be the next question anyone debugging the code would have, so it'd be a great help. All this should be an excellent showcase for what macros can do, splitting an expression into conjunctive terms, and finding the variables.)

@masak
Copy link
Owner Author

masak commented Feb 21, 2019

Of course, this has eerie pre-echoes of the omnipotent assert statement from #417. Come to think of it, there aren't miles of difference between PRE and assert. Surely they could share some code paths.

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

No branches or pull requests

1 participant