Skip to content

Commit c31dedb

Browse files
committed
Fix PFA in combination with pipeline operator optimizations
1 parent 6970210 commit c31dedb

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

src/main/php/lang/ast/emit/EmulatePipelines.class.php

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,36 @@
11
<?php namespace lang\ast\emit;
22

3-
use lang\ast\nodes\{CallableExpression, CallableNewExpression, Variable};
3+
use lang\ast\nodes\{CallableExpression, CallableNewExpression, Variable, Placeholder};
44

55
/**
66
* Emulates pipelines / the pipe operator, including a null-safe version.
77
*
8+
* ```php
9+
* // Enclose expressions as follows:
10+
* $in |> $expr;
11+
* ($expr)($in);
12+
*
13+
* // Optimize for first-class callables with single placeholder argument:
14+
* $in |> strlen(...);
15+
* strlen($in);
16+
* ```
17+
*
818
* @see https://wiki.php.net/rfc/pipe-operator-v3
919
* @see https://externals.io/message/107661#107670
1020
* @test lang.ast.unittest.emit.PipelinesTest
1121
*/
1222
trait EmulatePipelines {
1323

24+
private function singlePlaceholder($arguments) {
25+
return 1 === sizeof($arguments) && $arguments[0] instanceof Placeholder;
26+
}
27+
1428
protected function emitPipeTarget($result, $target, $arg) {
15-
if ($target instanceof CallableNewExpression) {
29+
if ($target instanceof CallableNewExpression && $this->singlePlaceholder($target->arguments)) {
1630
$target->type->arguments= [new Variable(substr($arg, 1))];
1731
$this->emitOne($result, $target->type);
1832
$target->type->arguments= null;
19-
} else if ($target instanceof CallableExpression) {
33+
} else if ($target instanceof CallableExpression && $this->singlePlaceholder($target->arguments)) {
2034
$this->emitOne($result, $target->expression);
2135
$result->out->write('('.$arg.')');
2236
} else {

src/test/php/lang/ast/unittest/emit/CallableSyntaxTest.class.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,4 +315,14 @@ public function run() {
315315
}');
316316
Assert::equals('cba', $f('abc'));
317317
}
318+
319+
#[Test]
320+
public function partial_function_application_with_pipe() {
321+
$r= $this->run('class %T {
322+
public function run() {
323+
return ["hello world"] |> array_map(str_replace("hello", "hi", ?), ?);
324+
}
325+
}');
326+
Assert::equals(['hi world'], $r);
327+
}
318328
}

0 commit comments

Comments
 (0)