1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @author Patsura Dmitry https://github.com/ovr <[email protected]> |
4
|
|
|
*/ |
5
|
|
|
|
6
|
|
|
namespace PHPSA\Definition; |
7
|
|
|
|
8
|
|
|
use PHPSA\CompiledExpression; |
9
|
|
|
use PHPSA\Context; |
10
|
|
|
use PhpParser\Node; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* Class FunctionDefinition |
14
|
|
|
* @package PHPSA\Definition |
15
|
|
|
*/ |
16
|
|
|
class ClosureDefinition extends ParentDefinition |
17
|
|
|
{ |
18
|
|
|
/** |
19
|
|
|
* @todo Use Finder |
20
|
|
|
* |
21
|
|
|
* @var string |
22
|
|
|
*/ |
23
|
|
|
protected $filepath; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* @var Node\Expr\Closure |
27
|
|
|
*/ |
28
|
|
|
protected $statement; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* @var int |
32
|
|
|
*/ |
33
|
|
|
protected $returnTypes = CompiledExpression::MIXED; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* @var array |
37
|
|
|
*/ |
38
|
|
|
protected $possibleReturnTypes = array(); |
39
|
|
|
|
40
|
|
|
protected $symbolTable = []; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* @param Node\Expr\Closure $statement |
44
|
|
|
*/ |
45
|
|
|
public function __construct(Node\Expr\Closure $statement) |
46
|
|
|
{ |
47
|
|
|
$this->statement = $statement; |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @param Context $context |
52
|
|
|
*/ |
53
|
|
|
public function preCompile(Context $context) |
54
|
|
|
{ |
55
|
|
|
if ($this->statement->uses) { |
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Store variables from User to next restore Context |
58
|
|
|
*/ |
59
|
|
|
foreach ($this->statement->uses as $variable) { |
60
|
|
|
$variable = $context->getSymbol($variable->var); |
|
|
|
|
61
|
|
|
if ($variable) { |
62
|
|
|
$this->symbolTable[$variable->getName()] = clone $variable; |
63
|
|
|
} |
64
|
|
|
} |
65
|
|
|
} |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* Compile function to check it |
70
|
|
|
* |
71
|
|
|
* @param Context $context |
72
|
|
|
* @return bool |
73
|
|
|
*/ |
74
|
|
|
public function compile(Context $context) |
75
|
|
|
{ |
76
|
|
|
if ($this->compiled) { |
77
|
|
|
return true; |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
$context->setFilepath($this->filepath); |
81
|
|
|
$this->compiled = true; |
82
|
|
|
|
83
|
|
|
$context->clearSymbols(); |
84
|
|
|
$context->scopePointer = $this->getPointer(); |
85
|
|
|
$context->setScope(null); |
86
|
|
|
|
87
|
|
|
if (count($this->statement->stmts) == 0) { |
88
|
|
|
return $context->notice( |
89
|
|
|
'not-implemented-function', |
90
|
|
|
sprintf('Closure %s() is not implemented', $this->name), |
91
|
|
|
$this->statement |
92
|
|
|
); |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
if (count($this->statement->params) > 0) { |
96
|
|
|
/** @var Node\Param $parameter */ |
97
|
|
|
foreach ($this->statement->params as $parameter) { |
98
|
|
|
$context->addSymbol($parameter->name); |
99
|
|
|
} |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
foreach ($this->statement->stmts as $st) { |
103
|
|
|
\PHPSA\nodeVisitorFactory($st, $context); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
return true; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
/** |
110
|
|
|
* @param CompiledExpression[] $arguments |
111
|
|
|
* @param Context $context |
112
|
|
|
* @return CompiledExpression |
113
|
|
|
*/ |
114
|
|
|
public function run(array $arguments, Context $context) |
|
|
|
|
115
|
|
|
{ |
116
|
|
|
return new CompiledExpression(); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* @return string |
121
|
|
|
*/ |
122
|
|
|
public function getFilepath() |
123
|
|
|
{ |
124
|
|
|
return $this->filepath; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* @param string $filepath |
129
|
|
|
*/ |
130
|
|
|
public function setFilepath($filepath) |
131
|
|
|
{ |
132
|
|
|
$this->filepath = $filepath; |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* @return string |
137
|
|
|
*/ |
138
|
|
|
public function getNamespace() |
139
|
|
|
{ |
140
|
|
|
return $this->namespace; |
141
|
|
|
} |
142
|
|
|
} |
143
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.