1+ <?php namespace lang \ast \emit ;
2+
3+ use lang \ast \nodes \{CallableExpression , CallableNewExpression , Variable };
4+
5+ /**
6+ * Emulates pipelines / the pipe operator, including a null-safe version.
7+ *
8+ * @see https://wiki.php.net/rfc/pipe-operator-v3
9+ * @see https://externals.io/message/107661#107670
10+ * @test lang.ast.unittest.emit.PipelinesTest
11+ */
12+ trait EmulatePipelines {
13+
14+ protected function emitPipeTarget ($ result , $ target , $ arg ) {
15+ if ($ target instanceof CallableNewExpression) {
16+ $ target ->type ->arguments = [new Variable (substr ($ arg , 1 ))];
17+ $ this ->emitOne ($ result , $ target ->type );
18+ $ target ->type ->arguments = null ;
19+ } else if ($ target instanceof CallableExpression) {
20+ $ this ->emitOne ($ result , $ target ->expression );
21+ $ result ->out ->write ('( ' .$ arg .') ' );
22+ } else {
23+ $ result ->out ->write ('( ' );
24+ $ this ->emitOne ($ result , $ target );
25+ $ result ->out ->write (')( ' .$ arg .') ' );
26+ }
27+ }
28+
29+ protected function emitPipe ($ result , $ pipe ) {
30+
31+ // $expr |> strtoupper(...) => [$arg= $expr, strtoupper($arg)][1]
32+ $ t = $ result ->temp ();
33+ $ result ->out ->write ('[ ' .$ t .'= ' );
34+ $ this ->emitOne ($ result , $ pipe ->expression );
35+ $ result ->out ->write (', ' );
36+ $ this ->emitPipeTarget ($ result , $ pipe ->target , $ t );
37+ $ result ->out ->write ('][1] ' );
38+ }
39+
40+ protected function emitNullsafePipe ($ result , $ pipe ) {
41+
42+ // $expr ?|> strtoupper(...) => null === ($arg= $expr) ? null : strtoupper($arg)
43+ $ t = $ result ->temp ();
44+ $ result ->out ->write ('null===( ' .$ t .'= ' );
45+ $ this ->emitOne ($ result , $ pipe ->expression );
46+ $ result ->out ->write (')?null: ' );
47+ $ this ->emitPipeTarget ($ result , $ pipe ->target , $ t );
48+ }
49+ }
0 commit comments