Skip to content

Commit

Permalink
Add support for arrow functions
Browse files Browse the repository at this point in the history
(cherry picked from commit 000b8df)
  • Loading branch information
thegallagher authored and nikic committed Jan 13, 2025
1 parent caa9079 commit b446ec9
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 0 deletions.
37 changes: 37 additions & 0 deletions lib/PHPCfg/Op/Expr/ArrowFunction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

/**
* This file is part of PHP-CFG, a Control flow graph implementation for PHP
*
* @copyright 2015 Anthony Ferrara. All rights reserved
* @license MIT See LICENSE at the root of the project for more info
*/

namespace PHPCfg\Op\Expr;

use PHPCfg\Func;
use PHPCfg\Op\CallableOp;
use PHPCfg\Op\Expr;

class ArrowFunction extends Expr implements CallableOp
{
public Func $func;

public function __construct(Func $func, array $attributes = [])
{
parent::__construct($attributes);
$this->func = $func;
}

public function getVariableNames(): array
{
return ['result'];
}

public function getFunc(): Func
{
return $this->func;
}
}
23 changes: 23 additions & 0 deletions lib/PHPCfg/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,29 @@ protected function parseExpr_Closure(Expr\Closure $expr)
return $closure;
}

protected function parseExpr_ArrowFunction(Expr\ArrowFunction $expr)
{
$flags = Func::FLAG_CLOSURE;
$flags |= $expr->byRef ? Func::FLAG_RETURNS_REF : 0;
$flags |= $expr->static ? Func::FLAG_STATIC : 0;

$this->script->functions[] = $func = new Func(
'{anonymous}#' . ++$this->anonId,
$flags,
$this->parseTypeNode($expr->returnType),
null,
);
$stmts = [
new Stmt\Return_($expr->expr),
];
$this->parseFunc($func, $expr->params, $stmts);

$closure = new Op\Expr\ArrowFunction($func, $this->mapAttributes($expr));
$func->callableOp = $closure;

return $closure;
}

protected function parseExpr_ClassConstFetch(Expr\ClassConstFetch $expr)
{
$c = $this->readVariable($this->parseExprNode($expr->class));
Expand Down
48 changes: 48 additions & 0 deletions test/code/arrow_fn.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

$b = 1;
$fn = fn($a) => $b++ * $a;
$fn(3);
var_dump($b);
-----
Block#1
Expr_Assign
var: Var#1<$b>
expr: LITERAL(1)
result: Var#2
Expr_ArrowFunction<'{anonymous}#1'>
result: Var#3
Expr_Assign
var: Var#4<$fn>
expr: Var#3
result: Var#5
Expr_FuncCall
name: Var#4<$fn>
args[0]: LITERAL(3)
result: Var#6
Expr_FuncCall
name: LITERAL('var_dump')
args[0]: Var#1<$b>
result: Var#7
Terminal_Return

Function '{anonymous}#1': mixed
Block#1
Expr_Param
declaredType: mixed
name: LITERAL('a')
result: Var#1<$a>
Expr_BinaryOp_Plus
left: Var#2<$b>
right: LITERAL(1)
result: Var#3
Expr_Assign
var: Var#4<$b>
expr: Var#3
result: Var#5
Expr_BinaryOp_Mul
left: Var#4<$b>
right: Var#1<$a>
result: Var#6
Terminal_Return
expr: Var#6

0 comments on commit b446ec9

Please sign in to comment.