Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:126846 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id 2E4731A00BC for ; Wed, 19 Mar 2025 15:51:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1742399360; bh=YMo/ra6XqvAFGxYx1kUwewV65HGOIlwwTS+L1doS9YU=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=cJkbSPzNZ2tMZt5T3mM/zQaS4wk82dcxUo0uDLTpJgUH6WqguNQ0TmnCzESIUfcpz bcnOxweyc/Nb+72LFgcStp0tsSa6F4brfEtJELWjv/4m9OzZMGZr1+2qpuHhliWObX V7YSfCoMhUxOMAK4lDMrCcii49pmoIpTqbzUImsV0RxBYZaLbqvf733WV0jjORbJpC p94Wv/bUm426J7e/0qJ6ZwfOGK5CoS1kl9S8jfVvJfsH1c8Nnl1i9T1xqiBhN+v015 9onGgTWoqGaOmSxVwM0Pv7zYxK7ERs0rd9oEXoP4sLT6Ja/L8QtGxd0WgCQ/OkN0Zb q3MSwVhdkLCEg== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 030D9180053 for ; Wed, 19 Mar 2025 15:49:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=BAYES_05,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-yb1-f175.google.com (mail-yb1-f175.google.com [209.85.219.175]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Wed, 19 Mar 2025 15:49:19 +0000 (UTC) Received: by mail-yb1-f175.google.com with SMTP id 3f1490d57ef6-e4930eca0d4so5470585276.3 for ; Wed, 19 Mar 2025 08:51:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1742399510; x=1743004310; darn=lists.php.net; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=e6amd9reD0LoY4VbWWXa/zaPYUUbp3SBHU8SvCmZ8tg=; b=C+akbGKtgwMZVnuLV5FR3b9zQ3fnFvuVv8oq/lN0/ms5/gIrf1Zf1ZtV7HzDOOirS4 U8aepE+l3fzZtNw7EvBVIa5fdUmG8VF6jfaXjHegz1DFvePE+aJOILgBSBMUhl9DkD5+ bZVv4QS5Z6vNShgLPLxc06YigY7wMz7styTs7FJbSvx382TWZPcZpIOhBytBdCA5S7lr XL9zYN8pPMuAPSwRKjQ1lbXM33mJbTB+BKBykuy0KMVw4mYPpUhSThUnFlENqh+7YCNZ 7Swr6JT3Gm3aA3XXm4dapgYmOvRbLiO0LuMZpBUcVnsqYe03bTVgRqaZcVHDr8B2qKw2 d6SQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1742399510; x=1743004310; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=e6amd9reD0LoY4VbWWXa/zaPYUUbp3SBHU8SvCmZ8tg=; b=EboelD6j+Dju7kVlNadr/gu+dcoBxGnw/dVThrDHo2S1Z2ojs060xVNevTtvwtSF/i qac9m4rPM4byd+U73w+e7eNA3Iu0pW2lV3jgHuOBJFsJnJLJSZhW7Ht67mOp9ERx2R/Y SLtGqYomsWVzj1j+hiEe9QDQVlLZ1pTeJ0sqlgQx8Qr2F5NIbHrE2+Yn62EzYqWUB4FI 1ABiERooly9uVDj5tJGfrDlFnpOebm7ISmu4m5rnvjj3jWKROj+GlPCsI5b244C9mXJb JOe5V4EH9UmSfHzSHUmeJElkGWi0PkX0cJAMiHuOlsIH+rFZ6XjA09T9cpBgtzkqJzuf MSYg== X-Gm-Message-State: AOJu0YzaNvVOqIqn5jLNZKe2NOD4HrGA/am5PqG2RlMc08xzUc5zhBLu V9xiqXKNAVGfHWBxS+lJDWtme+muhcdI4J2WMJU4A93mvpd6qfyyEZy2UR8uN9VA6LbD0w0VmAn dS17CjA63wFaB89jBh2MD177wmBDwQVON7zNxLA== X-Gm-Gg: ASbGnctn2Ww/4cecsn2DyMjBQg6Tg+e+Eulq/Lz7L48XNJMAj9s4gZyytOrK62m9QUX d3PXv3mazF92OQnoH5Hrze8r7aSJunksLtQlRS/bS/rqw5FVmuepFVG6G1SdKDl8AEh/Yd976sw 6aiadXLij+8PQvy64zKWvfWAUjTbn/MOBbXuqY X-Google-Smtp-Source: AGHT+IHamgry18buU7JLjR9FwZxtDbtslRFcsDwRYaaWlBEZ94DO20Ol00XCJlWeApY7WqNZ+KqETKOLR7m2J33NA00= X-Received: by 2002:a05:690c:a8b:b0:6fe:b88e:4d86 with SMTP id 00721157ae682-7009bf76d55mr42083957b3.9.1742399510127; Wed, 19 Mar 2025 08:51:50 -0700 (PDT) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 References: <72bd5401-53a9-409f-ad45-687333401961@rwec.co.uk> <6987D912-CE46-4145-A8CE-732CA590A522@rwec.co.uk> In-Reply-To: <6987D912-CE46-4145-A8CE-732CA590A522@rwec.co.uk> Date: Wed, 19 Mar 2025 17:51:38 +0200 X-Gm-Features: AQ5f1JpaZmhwVzkWAUDtC3ah0aNd3HRko57HH8kTausduggnbma2POZFv1O5Wvk Message-ID: Subject: Re: [PHP-DEV] PHP True Async RFC - Stage 2 To: "Rowan Tommins [IMSoP]" Cc: internals@lists.php.net Content-Type: multipart/alternative; boundary="000000000000dbace60630b3ff6c" From: edmond.ht@gmail.com (Edmond Dantes) --000000000000dbace60630b3ff6c Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable > > "Cheating" in the sense that you wrote out a "general syntax", > I got it. > That's not the problem; the problem is that the following are all equivalent expressions: > (((foo()))) In principle, this is not a problem because the expression in parentheses preceded by `spawn` is unambiguously a call expression. That is, from an analysis perspective, everything is fine here because the expression `spawn ()` is a syntax error. On the other hand, the expression `spawn (())` is also an error, but a semantic one, because there is nothing to call. The expression spawn ((), (), ()) is also an error because it attempts to specify a list of parameters without a call expression. It seems I didn't make any mistakes anywhere? > > But from a user's point of view, I hate rules like that which mean subtle changes completely change the meaning of the code, in a very specific context. > From the user's perspective, what is the difference between these two expressions? ```php spawn function(): string { ... }; spawn (function(): string { ... }); ``` > > All of these are examples of the keyword being followed by *a function call*, not *any expression*. Which honestly I think is the right way to go. > I created these examples according to the syntax rules from the Bison file for `function_call`. Of course, I might have missed something, but overall, the list above essentially represents what `function_call` should expand into. If we define the rule `spawn function_call`, then `spawn` acts as a prefix in this expression. However, everything that is already defined for `function_call` in PHP must remain valid. If we take the most complex part: ```bison | callable_expr { $$ =3D CG(zend_lineno); } argument_list { $$ =3D zend_ast_create(ZEND_AST_CALL, $1, $3); $$->lineno =3D $2; } callable_expr: callable_variable { $$ =3D $1; } | '(' expr ')' { $$ =3D $2; } | dereferenceable_scalar { $$ =3D $1; } | new_dereferenceable { $$ =3D $1; } ; ``` we can see that the expression (((some()))) corresponds to the second line, and arguments must follow. However, in this case, arguments become *mandatory*. This means that after (((some()))), there must also be (). And another good thing about this syntax: a coroutine is an execution context, and a function call is a transition to a block of code. This means that the expression `spawn function_call` can be understood literally as: * Create a new execution context * Execute `function_call` The syntax for `function_call` is already defined in PHP, and nothing changes in it. The second form of the `spawn` expression is: ```php spawn inline_function ``` where inline_function is a definition from bison: ```bison inline_function: function returns_ref backup_doc_comment '(' parameter_list ')' lexical_vars return_type ...; ``` Another advantage of this solution is that if `function_call` constructs change in the future, we won=E2=80=99t need to modify the definitions for `= spawn`. > > If it's going to be a special case for an "inline coroutine", just use a keyword other than "function", so it doesn't look like an expression when it's not, like "spawn block { ... }"; or no keyword at all, just "spawn { ... }" > Well, yes, but here we again face the issue with `returnType` syntax, which ends up hanging in the air... --000000000000dbace60630b3ff6c Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
>
>=C2=A0 "Cheating" in the sense that you wrote out a "general syntax= ",
>
I got it.

> That's not the pro= blem; the problem is that the following are all equivalent expressions:
= >=C2=A0 (((foo())))

In principle, this is not a problem because the expressi= on in parentheses preceded by `spawn` is unambiguously a call expression.= =C2=A0
That is, from an analysis perspective, everything is fine = here because the expression `spawn ()` is a syntax error.

On the ot= her hand, the expression `spawn (())` is also an error, but a semantic one,= because there is nothing to call.

The expression = spawn ((), (), ()) is also an error because it attempts to spe= cify a list of parameters without a call expression.=C2=A0=C2=A0
=
It seems I didn't make any mistakes anywhere?=C2=A0=C2= =A0

>
> But from a user's point o= f view, I hate rules like that which mean subtle changes completely change = the meaning of the code, in a very specific context.=C2=A0
>

From the user's perspective, what is the difference betwee= n these two expressions? =C2=A0

```php
spawn function(): s= tring { ... };
spawn (function(): string { ... });
```

>
>=C2=A0 All of these are examples of the keyword being followed by *a function call= *, not *any expression*. Which honestly I think is the right way to go.
= >

I created these examples according to the syn= tax rules from the Bison file for `function_call`.=C2=A0
Of cours= e, I might have missed something, but overall, the list above essentially r= epresents what `function_call` should expand into. =C2=A0

If we defi= ne the rule `spawn function_call`, then `spawn` acts as a prefix in this ex= pression. However, everything that is already defined for `function_call` i= n PHP must remain valid. =C2=A0

If we take the most complex part: = =C2=A0
```bison
| =C2=A0 callable_expr { $<num>$ =3D CG(zend_li= neno); } argument_list {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 $$ =3D zend_ast_cre= ate(ZEND_AST_CALL, $1, $3);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 $$->lineno = =3D $<num>2;
=C2=A0 =C2=A0 }

callable= _expr:
=C2=A0 =C2=A0 callable_variable =C2=A0 =C2=A0 =C2=A0 { $$ =3D $1;= }
=C2=A0 | '(' expr ')' =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 { $$ =3D $2; }
=C2=A0 | dereferenceable_scalar { $$ =3D $1; }
=C2= =A0 | new_dereferenceable =C2=A0 =C2=A0{ $$ =3D $1; }
;
``= `

we can see that the expression (((some()))= ) corresponds to the second line, and arguments must follow.=C2=A0
However, in this case, arguments become mandatory= . This means that after (((some()))), there must also be ().=C2=A0=C2=A0

And another good thing abo= ut this syntax: a coroutine is an execution context, and a function call is= a transition to a block of code.=C2=A0
This means that the expre= ssion `spawn function_call` can be understood literally as: =C2=A0

*= Create a new execution context =C2=A0
* Execute `function_call` =C2=A0<= br>
The syntax for `function_call` is already defined in PHP, and nothin= g changes in it.=C2=A0=C2=A0

The second form o= f the `spawn` expression is: =C2=A0
```php
spawn inline_function
<= /div>
```

where inline_function is a definitio= n from bison:

```bison
inline_function:<= /div>
function returns_ref backup_doc_comment '(' parameter_l= ist ')' lexical_vars return_type
...;
```

Another advantage of this solution is that if `function_ca= ll` constructs change in the future, we won=E2=80=99t need to modify the de= finitions for `spawn`.=C2=A0=C2=A0

>
>= ;=C2=A0 If it's going to be a special case for an "inline coroutine",= just use a keyword other than "function", so it doesn't look= like an expression when it's not, like "spawn block { ... }"= ; or no keyword at all, just "spawn { ... }"
>
Well, yes, but here we again face the issue with `returnType` = syntax, which ends up hanging in the air...=C2=A0=C2=A0
--000000000000dbace60630b3ff6c--