PHP header files, restrict to declaring code only

  105660
May 10, 2019 12:29 kjarli@gmail.com (Lynn)
Hello everyone!

This is my first mail to the internals, my apologies if I made a mistake
somewhere.

I would like to propose a new type of php "file" called "phph", short for
"php-header".
This file could receive an optional open-tag: `
    
  105661
May 10, 2019 12:37 nikita.ppv@gmail.com (Nikita Popov)
On Fri, May 10, 2019 at 2:30 PM Lynn <kjarli@gmail.com> wrote:

> Hello everyone! > > This is my first mail to the internals, my apologies if I made a mistake > somewhere. > > I would like to propose a new type of php "file" called "phph", short for > "php-header". > This file could receive an optional open-tag: ` `declare(header=1)`, > not sure what's more feasible, or if there are better solutions. This open > tag could be > optional for forward compatibility towards omitting the tag. > > Php-header files would be allowed to only contain declaring code. This > means that any code > that would run "while loading", would not be allowed and cause a syntax > error in the same > fashion as trying to add a function call in the middle of a class > declaration. > > ```php > // forward compatible? change default in a major version? > // any other ideas? > declare(header=1); > > // syntax errors: > echo 'foo'; > $a = 'b'; > > // valid > class Foo {} > interface Bar {} > function baz() {} > // etc > ``` > > By restricting it to declaration only, it would make it possible to add > extra features to > classes, such as annotations as there are a lot less edge cases to think > about: > > ```php > @trigger_error('Foo is deprecated as of 2.0, use Bar instead', > E_USER_DEPRECATED); > class Foo {} > ``` > > New scenario could be: > ```php > declare(header=1); > > use Php\Debugging\Annotations\Deprecated; > > @Deprecated('Foo is deprecated as of 2.0, use Bar instead'); > class Foo {} > ``` > > This is a pretty rough sketch, and I'm not exactly sure if this is doable. > I'm really eager > to have native support for annotations and perhaps this idea could inspire > someone with a > solution to make this feasible. > > Regards, > Lynn van der Berg >
Hi Lynn, I'm not sure I understood what the benefit of introducing a header file concept will be. Could you elaborate more on how this will help annotations (or other functionality)? Nikita
  105662
May 10, 2019 13:14 kjarli@gmail.com (Lynn)
Hi Nikita,

By limiting a header file to declaring code only, a couple of issues could
be tackled:

1. No side effects when loading files. You can assume the global state
remains the same, no
   code is executed by this file, and no output can be sent.
2. Certain features, can be restricted to php-header files only, meaning it
does not affect
   "normal" PHP files. This might open up a whole new range of syntax
possibilities that
   are currently blocked, such as `@trigger_error()` vs `@Annotation()`.

I can understand if those reasons are not enough to merit a whole new
concept as a header
file as it might introduce more complexity than it's worth.

Regards,
Lynn van der Berg


On Fri, May 10, 2019 at 2:37 PM Nikita Popov ppv@gmail.com> wrote:

> On Fri, May 10, 2019 at 2:30 PM Lynn <kjarli@gmail.com> wrote: > >> Hello everyone! >> >> This is my first mail to the internals, my apologies if I made a mistake >> somewhere. >> >> I would like to propose a new type of php "file" called "phph", short for >> "php-header". >> This file could receive an optional open-tag: `> `declare(header=1)`, >> not sure what's more feasible, or if there are better solutions. This open >> tag could be >> optional for forward compatibility towards omitting the tag. >> >> Php-header files would be allowed to only contain declaring code. This >> means that any code >> that would run "while loading", would not be allowed and cause a syntax >> error in the same >> fashion as trying to add a function call in the middle of a class >> declaration. >> >> ```php >> > // forward compatible? change default in a major version? >> // any other ideas? >> declare(header=1); >> >> // syntax errors: >> echo 'foo'; >> $a = 'b'; >> >> // valid >> class Foo {} >> interface Bar {} >> function baz() {} >> // etc >> ``` >> >> By restricting it to declaration only, it would make it possible to add >> extra features to >> classes, such as annotations as there are a lot less edge cases to think >> about: >> >> ```php >> > @trigger_error('Foo is deprecated as of 2.0, use Bar instead', >> E_USER_DEPRECATED); >> class Foo {} >> ``` >> >> New scenario could be: >> ```php >> > declare(header=1); >> >> use Php\Debugging\Annotations\Deprecated; >> >> @Deprecated('Foo is deprecated as of 2.0, use Bar instead'); >> class Foo {} >> ``` >> >> This is a pretty rough sketch, and I'm not exactly sure if this is doable. >> I'm really eager >> to have native support for annotations and perhaps this idea could inspire >> someone with a >> solution to make this feasible. >> >> Regards, >> Lynn van der Berg >> > > Hi Lynn, > > I'm not sure I understood what the benefit of introducing a header file > concept will be. Could you elaborate more on how this will help annotations > (or other functionality)? > > Nikita >
  105663
May 10, 2019 13:40 mdwheele@ncsu.edu (Dustin Wheeler)
On Fri, May 10, 2019 at 9:15 AM Lynn <kjarli@gmail.com> wrote:
> > 2. Certain features, can be restricted to php-header files only, meaning it > does not affect > "normal" PHP files. This might open up a whole new range of syntax > possibilities that > are currently blocked, such as `@trigger_error()` vs `@Annotation()`. >
Hi Lynn, thank you for opening this discussion! Could you explain how the range of syntax you suggest (regarding annotations) is currently blocked? I'm not challenging your claim; I *personally* don't know and am interested. While certainly not supported natively, comment-based "annotations" can be implemented in user-land and processed via reflection (See doctrine-annotations[1]). There has also been previous work and discussion in the annotation space [2][3][4][5]. Based on my light reading, I couldn't find any objections to annotations with side-effects, but I could see that as an argument. However, I'm more curious what your perspective is. Personally, I really like the idea of being able to declare "side-effect free" as a feature. I don't know if I prefer the idea of a `phph` file, distinguished by extension (so I'm glad you mention alternatives such as `declare`). That said, I think that's mostly from shock and not wanting to ever go back to a world that included *.php4, *.php5, *.phtml, etc. :) Hope all is well, 1: https://www.doctrine-project.org/projects/doctrine-annotations/en/latest/index.html 2: https://wiki.php.net/rfc/annotations 3: https://externals.io/message/82813 4: https://externals.io/message/64895 5: https://externals.io/message/64722 -- Dustin Wheeler | Software Developer NC State University mdwheele@ncsu.edu "If you don't know where you're going, it's easy to iteratively not get there."
  105664
May 10, 2019 14:12 kjarli@gmail.com (Lynn)
On Fri, May 10, 2019 at 3:40 PM Dustin Wheeler <mdwheele@ncsu.edu> wrote:

> On Fri, May 10, 2019 at 9:15 AM Lynn <kjarli@gmail.com> wrote: > > > > 2. Certain features, can be restricted to php-header files only, meaning > it > > does not affect > > "normal" PHP files. This might open up a whole new range of syntax > > possibilities that > > are currently blocked, such as `@trigger_error()` vs `@Annotation()`. > > > > Hi Lynn, thank you for opening this discussion! > > Could you explain how the range of syntax you suggest (regarding > annotations) is currently blocked? I'm not challenging your claim; I > *personally* don't know and am interested. While certainly not > supported natively, comment-based "annotations" can be implemented in > user-land and processed via reflection (See doctrine-annotations[1]). > There has also been previous work and discussion in the annotation > space [2][3][4][5]. Based on my light reading, I couldn't find any > objections to annotations with side-effects, but I could see that as > an argument. However, I'm more curious what your perspective is. >
Hi Dustin, Currently with Doctrine Annotations, inspired by that of Java as far as I know, the syntax would be ambiguous, at least until the closing semi-colon. I'm no expert on which syntax is or isn't possible, I remember this one being a potential issue and introducing complexity in the parser due to the silencing operator. ```php @SomeAnnotation() class {} // versus @SomeFunctionBeingSilenced(); class {} ``` You are correct that annotations are possible via user-land packages. I'm personally hoping to see this feature come to native PHP, making it possible to simplify the usage and possibly performance. I've been brainstorming around another feature to unify variable inspections, which would make annotation reading a whole lot simpler [1], but could also be done in Reflection. Annotations are my primary example for header files, as they share the same concept, they are declaring code only and they don't have side effects.
> Personally, I really like the idea of being able to declare > "side-effect free" as a feature. I don't know if I prefer the idea of > a `phph` file, distinguished by extension (so I'm glad you mention > alternatives such as `declare`). That said, I think that's mostly from > shock and not wanting to ever go back to a world that included *.php4, > *.php5, *.phtml, etc. :) >
I'm not sure if a `.phph` file extension is required for this feature to work, though it might simplify its implementation. While I certainly share your concern about multiple extensions, my experience with other languages makes me believe that this would not be much of an issue. With header files being an opt-in feature, it hopefully won't make php more complex for developers new to PHP.
> Hope all is well, > > 1: > https://www.doctrine-project.org/projects/doctrine-annotations/en/latest/index.html > 2: https://wiki.php.net/rfc/annotations > 3: https://externals.io/message/82813 > 4: https://externals.io/message/64895 > 5: https://externals.io/message/64722 > > -- > Dustin Wheeler | Software Developer > NC State University > mdwheele@ncsu.edu > "If you don't know where you're going, it's easy to iteratively not get > there." > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php >
Apologies for my previous message being top posted, I hope this message arrives in a better format! Regards, Lynn van der Berg 1: https://gist.github.com/linaori/af50c1692e3d360d2e550b05e6121e58#future-possibilities
  105668
May 10, 2019 21:09 me@kelunik.com (Niklas Keller)
Instead of introducing a declare option or special open tag, how about
another "include" construct, that only allows side-effect free (apart
from class loading) operations?

e.g. "require_noexec 'foobar.php'"

Regards, Niklas
  105684
May 13, 2019 09:59 kjarli@gmail.com (Lynn)
> Instead of introducing a declare option or special open tag, how about > another "include" construct, that only allows side-effect free (apart > from class loading) operations? > > e.g. "require_noexec 'foobar.php'" > > Regards, Niklas >
Hi Niklas, That's indeed a very interesting alternative! I've given it some thought in regards in the context of no side-effects and I really like the idea as it sounds easier to implement. With an alternative as such, I see one major roadblock, perhaps it can be solved? These days I personally hardly ever write require/include statements, composer does this for me with autoloading. For composer it would probably mean an "all or nothing" when it comes to picking the keyword to "require" or "require without side-effects". This makes it hard, if not impossible, to trigger deprecations from deprecated interfaces, unless you use something too hook into autoloading and check if there were `@deprecated` annotations on the class, interface, etc. This means that a feature that worked by default, would be broken and risk potential issues when upgrading. Following this strategy, it would put the responsibility of loading the files at the developer that consumes the (public) API, rather than the developer that (public) API. I believe the public API should define whether or not it can, or must be, be loaded without side effects without any worries for the developer consuming that public API. This is why I initially tried to come up with a strategy that allows you to define it in the file (one way or another). Note that my example with composer is tailored around my specific use-case and that a new function, keyword or statement might be more suitable for developers that explicitly load their code without autoloading. Regards, Lynn van der Berg
  105685
May 13, 2019 12:48 johannes@schlueters.de (Johannes =?ISO-8859-1?Q?Schl=FCter?=)
On Fr, 2019-05-10 at 15:14 +0200, Lynn wrote:
> Hi Nikita, > > By limiting a header file to declaring code only, a couple of issues > could > be tackled: > > 1. No side effects when loading files. You can assume the global > state > remains the same, no >    code is executed by this file, and no output can be sent.
Mind that this won't be side-effect free. Declaring a class/function is a side-effect in itself. For dealing with syntax differences we could use the declare() statement, as used for strict_types or encoding. A question is whether it is worthwhile to have multiple syntaxes in parallel. This adds burden for developers using PHP, (i.e. copying code from tutorials or other files might fail sometimes etc.) tools processing PHP (IDEs, code analyzers, ...) and language developers (new syntax changes have to be evaluated for both contexts) If this were a strategy to transition to a new syntax (deprecating "old PHP") such a mechanism would be the way to go. For just having alternatives to avoid a syntax conflict cost imo is too big. johannes
  105706
May 14, 2019 18:48 larry@garfieldtech.com ("Larry Garfield")
On Mon, May 13, 2019, at 7:49 AM, Johannes Schlüter wrote:
> On Fr, 2019-05-10 at 15:14 +0200, Lynn wrote: > > Hi Nikita, > > > > By limiting a header file to declaring code only, a couple of issues > > could > > be tackled: > > > > 1. No side effects when loading files. You can assume the global > > state > > remains the same, no > >    code is executed by this file, and no output can be sent. > > Mind that this won't be side-effect free. Declaring a class/function is > a side-effect in itself. > > For dealing with syntax differences we could use the declare() > statement, as used for strict_types or encoding. > > A question is whether it is worthwhile to have multiple syntaxes in > parallel. This adds burden for developers using PHP, (i.e. copying code > from tutorials or other files might fail sometimes etc.) tools > processing PHP (IDEs, code analyzers, ...) and language developers (new > syntax changes have to be evaluated for both contexts) > > If this were a strategy to transition to a new syntax (deprecating "old > PHP") such a mechanism would be the way to go. For just having > alternatives to avoid a syntax conflict cost imo is too big. > > johannes
Another possible place such a marker could be useful is in the new preloading functionality in 5.4. Any file that is preloaded is going to never execute again, ever. That means preloading a file that has both symbol declarations and executing global code could lead to weird results. I could see a preloader that would only try to preload symbol-only files. That said... most polyfill files, of which there are a decent number, do some variation on: Which would then be incompatible with such a check, yet are perfectly valid to preload; maybe even an especially good case for preloading. So such a strict check is probably unwise. Maybe it would be helpful for the various experimental "precompile PHP" efforts, like what Anthony Ferrara has been doing? I've no idea there. I appreciate the intent here, and agree most code files should be symbol-only, but I'm not sure there's a strong enough use case in practice for it. That said, were it to be adopted I would strongly favor a declare rather than a different file extension or tag. Something like: That would be the least obtrusive way of adding it, I think. --Larry Garfield
  105715
May 15, 2019 15:37 robehickman@gmail.com (Robert Hickman)
> > That said... most polyfill files, of which there are a decent number, do some variation on: > > > if (!function_exists('coolness')) { > function coolness(int $coolLevel) { ... } > } > ?> >
I can see quite a lot that could be done with preloading by executing code once, essentially compile time code execution. For example, choose which database interface is being used once, instead of every time the script runs. Or compile 'fluent call chains' into a more efficient form. If the AST were accessible, there is quite a lot more that could be done.