11<?php namespace lang \ast \emit ;
22
33use lang \ast \Node ;
4- use lang \ast \nodes \{Expression , InstanceExpression , ScopeExpression , Literal };
4+ use lang \ast \nodes \{Expression , InstanceExpression , ScopeExpression , Literal , Placeholder };
55
66/**
77 * Rewrites callable expressions to `Callable::fromClosure()`
88 *
99 * @see https://www.php.net/manual/de/closure.fromcallable.php
10+ * @see https://wiki.php.net/rfc/clone_with_v2
1011 * @see https://wiki.php.net/rfc/first_class_callable_syntax
12+ * @see https://wiki.php.net/rfc/partial_function_application_v2
1113 */
1214trait CallablesAsClosures {
15+ use RewritePartialFunctionApplications { emitCallable as emitPartial; }
1316
1417 private function emitQuoted ($ result , $ node ) {
1518 if ($ node instanceof Literal) {
1619
17- // Rewrite f() => "f"
20+ // Rewrite f(... ) => "f"
1821 $ result ->out ->write ('" ' .trim ($ node , '" \'' ).'" ' );
1922 } else if ($ node instanceof InstanceExpression) {
2023
21- // Rewrite $this->f => [$this, "f"]
24+ // Rewrite $this->f(...) => [$this, "f"]
2225 $ result ->out ->write ('[ ' );
2326 $ this ->emitOne ($ result , $ node ->expression );
2427 $ result ->out ->write (', ' );
2528 $ this ->emitQuoted ($ result , $ node ->member );
2629 $ result ->out ->write ('] ' );
2730 } else if ($ node instanceof ScopeExpression) {
2831
29- // Rewrite T::f => [T::class, "f"]
32+ // Rewrite T::f(...) => [T::class, "f"]
3033 $ result ->out ->write ('[ ' );
3134 if ($ node ->type instanceof Node) {
3235 $ this ->emitOne ($ result , $ node ->type );
@@ -38,7 +41,7 @@ private function emitQuoted($result, $node) {
3841 $ result ->out ->write ('] ' );
3942 } else if ($ node instanceof Expression) {
4043
41- // Rewrite T::{<f>} => [T::class, <f>]
44+ // Rewrite T::{<f>}(...) => [T::class, <f>]
4245 $ this ->emitOne ($ result , $ node ->inline );
4346 } else {
4447
@@ -50,6 +53,8 @@ private function emitQuoted($result, $node) {
5053 protected function emitCallable ($ result , $ callable ) {
5154 if ($ callable ->expression instanceof Literal && 'clone ' === $ callable ->expression ->expression ) {
5255 $ result ->out ->write ('fn($o) => clone $o ' );
56+ } else if ([Placeholder::$ VARIADIC ] !== $ callable ->arguments ) {
57+ $ this ->emitPartial ($ result , $ callable );
5358 } else {
5459 $ result ->out ->write ('\Closure::fromCallable( ' );
5560 $ this ->emitQuoted ($ result , $ callable ->expression );
0 commit comments