Re: I declare declare to be useful... potentially...
| From: | Rowan Collins | Date: | Sun, 08 Feb 2015 19:25:03 +0000 |
| Subject: | Re: I declare declare to be useful... potentially... | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-82161@lists.php.net to get a copy of this message | ||
On 08/02/2015 09:20, Patrick Schaaf wrote:
Am 08.02.2015 03:39 schrieb "Rasmus Lerdorf" <rasmus@lerdorf.com>:I agree with pretty much everything in this post. While it is messy to have a language with too many runtime behaviours, it's much more useful to have them explicitly and lexically scoped than to have them either global or dnyamically toggled at runtime, which are the options ini settings have now. The problem, I guess, is in how you implement it - does the declare directive have to cause the compiler to emit different opcodes for this file, or does it require extra code to run on every entry and exit. For instance, this would be really useful to wrap around legacy code that is being phased out rather than improved: declare(error_handling=E_WARNING|E_ERROR) { function foo() { ... } function bar() { ... } } The only way I can think to implement that is to add opcodes to the beginning and end of each function to push and pop the setting each time the code is called - the low-level equivalent of "$old_eh = error_reporting(E_WARNING|E_ERROR); ... error_reporting($old_eh);" I don't know how much overhead that would incur in practice; presumably unlike @ it wouldn't defeat optimisations, since the start of a function definition is always a boundary to that kind of thing anyway?Basically declare() does not respect function scope, but it doesn't let you know that. There is a reason we haven't used declare() for anything real.That is absolutely awful. But it's a fault with declare. Can't that be fixed once and for all by fixing declare parsing - when used that way inside a function, make its scope end with the end of the function, as we would all have expected it to be, and as it would be when used in the declare-with-a-block-form? I chose a different subject, as it's an issue separate from the strict typing thing itself. declare is, to me, a very useful construct. Somebody recently wrote that it is "just" a localized version of ini settings. That's right - it's the way language (interpretation) settings SHOULD BE: give the power LOCALLY to the coder, with effects LOCALLY in the file and/or scope where it is used, and for the selective purpose given in the declare conditions. This is the ONLY sane way to make such switches. It does not magically make code fail when nonlocal stuff (ini settings) is changed, and it is more-locally reversible, in its block form, when needed. It is all about giving power to the calling code, which is a good thing with the potential to resolve several of the long standing discussions on this list. I applaud Andrea for having seen this, and followed through with it, regarding strict type checks. Other issues that may be solved in a similar way, using declare as a local behaviour switch, are: * scoped, stacked modifications to error handling:* overriding, for a while, the current global error handler * autoconversion of errors to exceptions * autoconversion of exceptions to errors * suppression of error output (without affecting handling itself)* assertions/pre/postconditions, as recently discussed in the DbC thread * an in-PHP alternative to #ifdeffery, for leaving out code fragments based on the presence or values of already defined constants. Something I'd love to have.... This would provide a nicer way for BC and FC handling code, and if declare could be made to pretty much ignore the detailled content of its block (except for curly brace matching), would even work out for reserved keyword issues. * a generic way to change ini settings with automatic resetting at the end of the declare block/scope. * a hook for extensions to introduce new declare conditions, with the extension getting, in AST form, the condition value, and a way to selectively operate on the declare block or rest-of-file AST. So there you have it, my vision of what poor mistreated declare could be. Do with it what you like. But I had to write it down...
Apart from fixing the declare function scoping thing, a second modification might be needed in general, to go forward and backward with it afterwards: _ignore_ unknown declare conditions, with a safe semantic meaning of leaving out the block (or rest of file, in the nonblock form, a la __halt_compiler!) altogether.I think it's a shame that declare() itself wasn't always implemented with forwards-compatibility in mind. In some cases (probably including strict types) the declaration itself could be completely ignored, rather than causing the file to be parsed as empty (which is probably no more useful than it emitting a parse error). I wonder if it's feasible to write extensions for *old* versions of PHP which add new declare() directives? Regards, -- Rowan Collins [IMSoP]