Re: [PHP-DEV] print with newline

  104578
March 4, 2019 15:30 svnpenn@gmail.com (Steven Penny)
On Mon, 04 Mar 2019 02:23:46, Peter Kokot wrote:
> Now, interesting is that in bash and some langs (where the main > environment is CLI), there is by default newline echoed. In PHP and > other languages there isn't. Changing default functionality of echo in > PHP is like changing left-hand traffic countries to use right-hand > traffic. A new function name would be needed for that. You can start > with creating an extension for this.
I think the best option is a new function like "puts" or "posix_puts". I looked into this but im having trouble. i started with "var_dump" because that does produce a newline by default [1]: php_printf("%sbool(false)\n", COMMON); new function would be most similar to "print", so i went to look at that code, but it seems "print" uses "echo" internally [2]: opline = zend_emit_op(NULL, ZEND_ECHO, &expr_node, NULL); so then i went to look at "echo" code. however i cant actually seen to find where that is defined, as the PHP codebase is... byzantine. it seems ZEND_ECHO is handled by "zend_write" [3]: zend_write(ZSTR_VAL(str), ZSTR_LEN(str)); which is handled by "write_function" [4]: zend_write = (zend_write_func_t) utility_functions->write_function; which is handled by "php_output_write" [5]: zuf.write_function = php_output_write; which is handled by "php_output_op" [6]: php_output_op(PHP_OUTPUT_HANDLER_WRITE, str, len); which is handled by "ub_write" [7]: sapi_module.ub_write(context.out.data, context.out.used); which is handled by "orig_ub_write" [8]: sapi_module.ub_write = orig_ub_write; which is handled by... "ub_write"? [9]: size_t (*orig_ub_write)(const char *str, size_t str_length) = sapi_module.ub_write; it seems like a circular definition. surely i am getting something wrong, and is it really need to go 8 levels of abstraction to write to standard output? [1] https://github.com/php/php-src/blob/df57395/ext/standard/var.c#L109 [2] https://github.com/php/php-src/blob/df57395/Zend/zend_compile.c#L7361 [3] https://github.com/php/php-src/blob/df57395/Zend/zend_vm_def.h#L1584 [4] https://github.com/php/php-src/blob/df57395/Zend/zend.c#L810 [5] https://github.com/php/php-src/blob/df57395/main/main.c#L2140 [6] https://github.com/php/php-src/blob/df57395/main/output.c#L255 [7] https://github.com/php/php-src/blob/df57395/main/output.c#L1076 [8] https://github.com/php/php-src/blob/df57395/ext/opcache/ZendAccelerator.c#L4211 [9] https://github.com/php/php-src/blob/df57395/ext/opcache/ZendAccelerator.c#L4126
  104579
March 4, 2019 16:02 krakjoe@gmail.com (Joe Watkins)
Afternoon Steven,

I'm not going to apologize for making a joke ... it was a joke ...

That being said, if you insist on pursuing an RFC for this, and would like
to get on with writing that RFC, then here is an initial patch:
https://gist.github.com/krakjoe/efff492611ce8f9fc12909023c89c7dc

Let compile time optimization of the call be implemented if the feature is
accepted, and don't worry about doing that yourself.

I haven't changed my mind, this is not justified in my opinion, but it is
just my opinion and I could have been more helpful yesterday ...

Cheers
Joe

On Mon, 4 Mar 2019 at 16:30, Steven Penny <svnpenn@gmail.com> wrote:

> On Mon, 04 Mar 2019 02:23:46, Peter Kokot wrote: > > Now, interesting is that in bash and some langs (where the main > > environment is CLI), there is by default newline echoed. In PHP and > > other languages there isn't. Changing default functionality of echo in > > PHP is like changing left-hand traffic countries to use right-hand > > traffic. A new function name would be needed for that. You can start > > with creating an extension for this. > > I think the best option is a new function like "puts" or "posix_puts". I > looked > into this but im having trouble. i started with "var_dump" because that > does > produce a newline by default [1]: > > php_printf("%sbool(false)\n", COMMON); > > new function would be most similar to "print", so i went to look at that > code, > but it seems "print" uses "echo" internally [2]: > > opline = zend_emit_op(NULL, ZEND_ECHO, &expr_node, NULL); > > so then i went to look at "echo" code. however i cant actually seen to find > where that is defined, as the PHP codebase is... byzantine. it seems > ZEND_ECHO > is handled by "zend_write" [3]: > > zend_write(ZSTR_VAL(str), ZSTR_LEN(str)); > > which is handled by "write_function" [4]: > > zend_write = (zend_write_func_t) utility_functions->write_function; > > which is handled by "php_output_write" [5]: > > zuf.write_function = php_output_write; > > which is handled by "php_output_op" [6]: > > php_output_op(PHP_OUTPUT_HANDLER_WRITE, str, len); > > which is handled by "ub_write" [7]: > > sapi_module.ub_write(context.out.data, context.out.used); > > which is handled by "orig_ub_write" [8]: > > sapi_module.ub_write = orig_ub_write; > > which is handled by... "ub_write"? [9]: > > size_t (*orig_ub_write)(const char *str, size_t str_length) = > sapi_module.ub_write; > > it seems like a circular definition. surely i am getting something wrong, > and > is it really need to go 8 levels of abstraction to write to standard > output? > > [1] https://github.com/php/php-src/blob/df57395/ext/standard/var.c#L109 > [2] https://github.com/php/php-src/blob/df57395/Zend/zend_compile.c#L7361 > [3] https://github.com/php/php-src/blob/df57395/Zend/zend_vm_def.h#L1584 > [4] https://github.com/php/php-src/blob/df57395/Zend/zend.c#L810 > [5] https://github.com/php/php-src/blob/df57395/main/main.c#L2140 > [6] https://github.com/php/php-src/blob/df57395/main/output.c#L255 > [7] https://github.com/php/php-src/blob/df57395/main/output.c#L1076 > [8] > https://github.com/php/php-src/blob/df57395/ext/opcache/ZendAccelerator.c#L4211 > [9] > https://github.com/php/php-src/blob/df57395/ext/opcache/ZendAccelerator.c#L4126 > > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
  104580
March 4, 2019 16:25 johannes@schlueters.de (Johannes =?ISO-8859-1?Q?Schl=FCter?=)
On Mo, 2019-03-04 at 07:30 -0800, Steven Penny wrote:
> On Mon, 04 Mar 2019 02:23:46, Peter Kokot wrote: > > > > Now, interesting is that in bash and some langs (where the main > > environment is CLI), there is by default newline echoed. In PHP and > > other languages there isn't. Changing default functionality of echo > > in > > PHP is like changing left-hand traffic countries to use right-hand > > traffic. A new function name would be needed for that. You can > > start > > with creating an extension for this. > I think the best option is a new function like "puts" or > "posix_puts". I looked > into this but im having trouble. i started with "var_dump" because > that does > produce a newline by default [1]: > >     php_printf("%sbool(false)\n", COMMON); > > new function would be most similar to "print", so i went to look at > that code, > but it seems "print" uses "echo" internally [2]: > >     opline = zend_emit_op(NULL, ZEND_ECHO, &expr_node, NULL);
What you are seeing is that "echo" and "print" are no functions, but language constructs (this is why the follow different rules, i.e. no need for parenthesis around parameters etc.) which makes them a bit special. Second thing you are seeing is PHP's modular architecture. The engine is it's own independent thing and you could (theoretically, not sure if that is fully kept) compile the engine stand-alone without "PHP" this is why zend_write is a hook, which is registered from PHP on startup. Second thing is that PHP's output doesn't go to the output directly, but goes to the SAPI layer into a server-environment specific API. Adding a new language construct is relatively complex as you have to extend the parser and the PHP syntax etc. The way I (spontaneously, without much thinking, so maybe bad) would do this by extending th ZEND_ECHO opcode (= bytecode command for the Zend virtual machine) with an operand which ells whether new line is requested or not and then in the compiler produce the according code. (see parser files and zend_compile for how echo/print are compiled) The flow there is PHP code is scanned&parsed into an AST, that AST is then compiled into opcode and that opcode is then executed on the VM (ad probably stored n opcode cache) Also mind that zend_vm_def.h isn't directly used while compiling the engine, but has to be processed using zend_vm_gen.php to generate the actual VM out of it. Oh and as another thought for implementation: Eventually this can be done in the parser already. Having    echoln "foo"; pretend to be parsed as     echo "foo", PHP_EOL; This could eventually be a change by touching the parser only. (but again - I didn't do any research on this, see zend_language_parser.y for the parsing rules for echo) Massively simpler is to create new thing as a function. Similar to printf(). For that you need a PHP_FUNCTION for the implementation and then an function entry using PHP_FE in some function table. See ext/standard/formatted_print.c for the implementation of printf() and friends and ext/standard/basic_functions.c for the function table. This can also be done in a custom extension see http://www.phpinternals book.com/php7/extensions_design/php_functions.html johannes P.S. I see this more as a learning exercise than as a project which will be added to PHP
  104606
March 6, 2019 15:45 chasepeeler@gmail.com (Chase Peeler)
On Mon, Mar 4, 2019 at 11:25 AM Johannes Schlüter <johannes@schlueters..de>
wrote:

> On Mo, 2019-03-04 at 07:30 -0800, Steven Penny wrote: > > On Mon, 04 Mar 2019 02:23:46, Peter Kokot wrote: > > > > > > Now, interesting is that in bash and some langs (where the main > > > environment is CLI), there is by default newline echoed. In PHP and > > > other languages there isn't. Changing default functionality of echo > > > in > > > PHP is like changing left-hand traffic countries to use right-hand > > > traffic. A new function name would be needed for that. You can > > > start > > > with creating an extension for this. > > I think the best option is a new function like "puts" or > > "posix_puts". I looked > > into this but im having trouble. i started with "var_dump" because > > that does > > produce a newline by default [1]: > > > > php_printf("%sbool(false)\n", COMMON); > > > > new function would be most similar to "print", so i went to look at > > that code, > > but it seems "print" uses "echo" internally [2]: > > > > opline = zend_emit_op(NULL, ZEND_ECHO, &expr_node, NULL); > > > What you are seeing is that "echo" and "print" are no functions, but > language constructs (this is why the follow different rules, i.e. no > need for parenthesis around parameters etc.) which makes them a bit > special. > > Second thing you are seeing is PHP's modular architecture. The engine > is it's own independent thing and you could (theoretically, not sure if > that is fully kept) compile the engine stand-alone without "PHP" this > is why zend_write is a hook, which is registered from PHP on startup. > Second thing is that PHP's output doesn't go to the output directly, > but goes to the SAPI layer into a server-environment specific API. > > Adding a new language construct is relatively complex as you have to > extend the parser and the PHP syntax etc. The way I (spontaneously, > without much thinking, so maybe bad) would do this by extending th > ZEND_ECHO opcode (= bytecode command for the Zend virtual machine) with > an operand which ells whether new line is requested or not and then in > the compiler produce the according code. (see parser files and > zend_compile for how echo/print are compiled) > > The flow there is PHP code is scanned&parsed into an AST, that AST is > then compiled into opcode and that opcode is then executed on the VM > (ad probably stored n opcode cache) > > Also mind that zend_vm_def.h isn't directly used while compiling the > engine, but has to be processed using zend_vm_gen.php to generate the > actual VM out of it. > > Oh and as another thought for implementation: Eventually this can be > done in the parser already. Having > echoln "foo"; > pretend to be parsed as > echo "foo", PHP_EOL; > This could eventually be a change by touching the parser only. (but > again - I didn't do any research on this, see zend_language_parser.y > for the parsing rules for echo) > > > Massively simpler is to create new thing as a function. Similar to > printf(). For that you need a PHP_FUNCTION for the implementation and > then an function entry using PHP_FE in some function table. > See ext/standard/formatted_print.c for the implementation of printf() > and friends and ext/standard/basic_functions.c for the function table. > This can also be done in a custom extension see http://www.phpinternals > book.com/php7/extensions_design/php_functions.html > > johannes > > P.S. I see this more as a learning exercise than as a project which > will be added to PHP > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > > I usually lean to the more permissive side when it comes to adding (or not removing) functions that are just syntactic sugar. "If it doesn't hurt,
then why not?" is my usual feeling. That being said, I am with the majority of commenters on this thread - I don't see why this is necessary. We aren't even talking about a new function that would wrap up two lines of codes into one line. It's just leaving off a few characters from something that already is one line. I also want to add that I HATE when I encounter other languages that automatically add the new line. I often write scripts with output like: Processing Foo...done Processing Bar...done Since the "Processing Foo..." is output first, followed by some processing time, before outputting "done" I often find myself having to look through documentation to figure out how to suppress the newline that was automatically added. On the flip side, I often find a lot of extra white space in my output from where I've added an additional newline to the output, not realizing one was already added for me. All that being said, if we WERE to move forward with one of the proposals (which it doesn't seem is going to happen), then it would need to be a new function. I can't see ANY advantage to the BC break that would be caused by modifying current functions/constructs - definitely not an advantage big enough to justify the downside. It looks like this would be a great opportunity for someone that wants to learn how to develop extensions to get their feet wet as well. -- -- Chase chasepeeler@gmail.com
  104625
March 10, 2019 19:28 tpunt@hotmail.co.uk (Thomas Punt)
> From: Steven Penny <svnpenn@gmail.com> > Sent: 04 March 2019 15:30 > To: internals@lists.php.net > Subject: Re: [PHP-DEV] print with newline > > I think the best option is a new function like "puts" or "posix_puts".
I'm fairly neutral on the feature, but I disagree with this being a function. It should be a language construct for parity with the echo and print. For what it's worth, I actually wrote an article about exactly this. Whilst it was more for didactic reasons (meaning that parts of the implementation could/should be changed), you may find it to be a nice read: https://phpinternals.net/articles/implementing_new_language_constructs_via_opcode_extending Cheers, Tom
  104629
March 10, 2019 19:57 krakjoe@gmail.com (Joe Watkins)
As a function it has parity with fputs ... even though fputs doesn't have
the same behaviour the two can be considered complimentary, and you would
want to be able to cuf(a) puts like fputs.

Regardless an RFC may go ahead without optimized implementation.

Cheers
Joe

On Sun, 10 Mar 2019, 20:28 Thomas Punt, <tpunt@hotmail.co.uk> wrote:

> > From: Steven Penny <svnpenn@gmail.com> > > Sent: 04 March 2019 15:30 > > To: internals@lists.php.net > > Subject: Re: [PHP-DEV] print with newline > > > > I think the best option is a new function like "puts" or "posix_puts". > > I'm fairly neutral on the feature, but I disagree with this being a > function. > It should be a language construct for parity with the echo and print. > > For what it's worth, I actually wrote an article about exactly this. Whilst > it was more for didactic reasons (meaning that parts of the implementation > could/should be changed), you may find it to be a nice read: > > https://phpinternals.net/articles/implementing_new_language_constructs_via_opcode_extending > > Cheers, > Tom >