Skip to content

Commit c833be0

Browse files
committed
Optimize passing constant expressions
1 parent 15452e6 commit c833be0

File tree

1 file changed

+34
-17
lines changed

1 file changed

+34
-17
lines changed

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

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

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

55
/**
66
* Rewrites partial function application as follows:
77
*
88
* ```php
99
* // Input:
10-
* $f= str_replace('test', result(), ?);
10+
* $f= str_replace('test', 'ok', ?);
1111
*
12+
* // Output:
13+
* $f= fn($arg) => str_replace('test', 'ok', $arg);
14+
*
15+
* // Input:
16+
* $f= str_replace('test', result(), ?);
17+
*
1218
* // Ouput:
1319
* $f= [
14-
* $a0= 'test',
15-
* $a1= result(),
16-
* fn($arg) => str_replace($a0, $a1, $arg)
17-
* ][2];
20+
* $temp= result(),
21+
* fn($arg) => str_replace('test', $temp, $arg)
22+
* ][1];
1823
* ```
1924
*
2025
* @see https://wiki.php.net/rfc/partial_function_application_v2
@@ -23,31 +28,43 @@ trait RewritePartialFunctionApplications {
2328

2429
protected function emitCallable($result, $callable) {
2530
if ([Placeholder::$VARIADIC] !== $callable->arguments) {
26-
$sig= $pass= '';
27-
$offset= 0;
28-
$result->out->write('[');
31+
$sig= '';
32+
$pass= $init= [];
2933
foreach ($callable->arguments as $argument) {
30-
$t= $result->temp();
3134
if (Placeholder::$VARIADIC === $argument) {
35+
$t= $result->temp();
3236
$sig.= ',...'.$t;
33-
$pass.= ',...'.$t;
37+
$pass[]= new UnpackExpression(new Variable(substr($t, 1)));
3438
} else if (Placeholder::$ARGUMENT === $argument) {
39+
$t= $result->temp();
3540
$sig.= ','.$t;
36-
$pass.= ','.$t;
41+
$pass[]= new Variable(substr($t, 1));
42+
} else if ($this->isConstant($result, $argument)) {
43+
$pass[]= $argument;
3744
} else {
38-
$pass.= ','.$t;
45+
$t= $result->temp();
46+
$pass[]= new Variable(substr($t, 1));
47+
$init[$t]= $argument;
48+
}
49+
}
50+
51+
// Initialize any non-constant expressions in place
52+
if ($init) {
53+
$result->out->write('[');
54+
foreach ($init as $t => $argument) {
3955
$result->out->write($t.'=');
4056
$this->emitOne($result, $argument);
4157
$result->out->write(',');
42-
$offset++;
4358
}
4459
}
4560

61+
// Emit closure invoking the callable expression
4662
$result->out->write('fn('.substr($sig, 1).')=>');
4763
$this->emitOne($result, $callable->expression);
48-
$result->out->write('('.substr($pass, 1).')');
49-
50-
$result->out->write(']['.$offset.']');
64+
$result->out->write('(');
65+
$this->emitArguments($result, $pass);
66+
$result->out->write(')');
67+
$init && $result->out->write(']['.sizeof($init).']');
5168
} else {
5269
parent::emitCallable($result, $callable);
5370
}

0 commit comments

Comments
 (0)