public function __construct(ITypeSystem $typeSystem, O\IEvaluationContext $evaluationContext) { parent::__construct($typeSystem); $this->evaluationContext = $evaluationContext; foreach ($evaluationContext->getVariableTable() as $variable => $value) { $this->setExpressionType(O\Expression::variable(O\Expression::value($variable)), $typeSystem->getTypeFromValue($value)); } }
public function testAssignmentToBinaryOperatorEquivalent() { foreach ([O\Operators\Assignment::EQUAL, O\Operators\Assignment::EQUAL_REFERENCE] as $operatorThatShouldNotChange) { $assignment = O\Expression::assign(O\Expression::variable(O\Expression::value('foo')), $operatorThatShouldNotChange, O\Expression::variable(O\Expression::value('bar'))); $this->assertSame($assignment, $assignment->toBinaryOperationEquivalent()); } $assignment = O\Expression::assign(O\Expression::variable(O\Expression::value('foo')), O\Operators\Assignment::ADDITION, O\Expression::variable(O\Expression::value('bar'))); $this->assertEquals(O\Expression::assign(O\Expression::variable(O\Expression::value('foo')), O\Operators\Assignment::EQUAL, O\Expression::binaryOperation(O\Expression::variable(O\Expression::value('foo')), O\Operators\Binary::ADDITION, O\Expression::variable(O\Expression::value('bar')))), $assignment->toBinaryOperationEquivalent()); }
public function testExpressionWalkerWorks() { $expression = O\Expression::variable(O\Expression::value('foo')); $expressionWalker = new O\DynamicExpressionWalker([O\ValueExpression::getType() => function (O\ValueExpression $expression) { return O\Expression::value('bar'); }]); $newExpression = $expressionWalker->walk($expression); $this->assertNotEquals($expression, $newExpression); $this->assertSame($newExpression->getName()->getValue(), 'bar'); }
public function parseExpressionNode(Node\Expr $node) { switch (true) { case $mappedNode = $this->parseOperatorNode($node): return $mappedNode; case $node instanceof Node\Scalar && ($mappedNode = $this->parseScalarNode($node)): return $mappedNode; case $node instanceof Node\Expr\Variable: return Expression::variable($this->parseNameNode($node->name)); case $node instanceof Node\Expr\Array_: return $this->parseArrayNode($node); case $node instanceof Node\Expr\FuncCall: return $this->parseFunctionCallNode($node); case $node instanceof Node\Expr\New_: return Expression::newExpression($this->parseNameNode($node->class), $this->parseNodes($node->args)); case $node instanceof Node\Expr\MethodCall: return Expression::methodCall($this->parseNode($node->var), $this->parseNameNode($node->name), $this->parseNodes($node->args)); case $node instanceof Node\Expr\PropertyFetch: return Expression::field($this->parseNode($node->var), $this->parseNameNode($node->name)); case $node instanceof Node\Expr\ArrayDimFetch: return Expression::index($this->parseNode($node->var), $node->dim === null ? null : $this->parseNode($node->dim)); case $node instanceof Node\Expr\ConstFetch: return Expression::constant($this->parseAbsoluteName($node->name)); case $node instanceof Node\Expr\ClassConstFetch: return Expression::classConstant($this->parseNameNode($node->class), $node->name); case $node instanceof Node\Expr\StaticCall: return Expression::staticMethodCall($this->parseNameNode($node->class), $this->parseNameNode($node->name), $this->parseNodes($node->args)); case $node instanceof Node\Expr\StaticPropertyFetch: return Expression::staticField($this->parseNameNode($node->class), $this->parseNameNode($node->name)); case $node instanceof Node\Expr\Ternary: return $this->parseTernaryNode($node); case $node instanceof Node\Expr\Closure: return $this->parseClosureNode($node); case $node instanceof Node\Expr\Empty_: return Expression::emptyExpression($this->parseNode($node->expr)); case $node instanceof Node\Expr\Isset_: return Expression::issetExpression($this->parseNodes($node->vars)); default: throw new ASTException('Cannot parse AST with unknown expression node: %s', get_class($node)); } }
public function expressions() { return [[O\Expression::arrayExpression([])], [O\Expression::arrayItem(null, O\Expression::value(0), false)], [O\Expression::assign(O\Expression::value(0), O\Operators\Assignment::EQUAL, O\Expression::value(0))], [O\Expression::binaryOperation(O\Expression::value(0), O\Operators\Binary::ADDITION, O\Expression::value(0))], [O\Expression::unaryOperation(O\Operators\Unary::PLUS, O\Expression::value(0))], [O\Expression::cast(O\Operators\Cast::STRING, O\Expression::value(0))], [O\Expression::closure(false, false, [], [], [])], [O\Expression::closureUsedVariable('var')], [O\Expression::emptyExpression(O\Expression::value(0))], [O\Expression::field(O\Expression::value(0), O\Expression::value(0))], [O\Expression::functionCall(O\Expression::value(0))], [O\Expression::index(O\Expression::value(0), O\Expression::value(0))], [O\Expression::invocation(O\Expression::value(0))], [O\Expression::issetExpression([O\Expression::value(0)])], [O\Expression::unsetExpression([O\Expression::value(0)])], [O\Expression::methodCall(O\Expression::value(0), O\Expression::value(0))], [O\Expression::newExpression(O\Expression::value(0))], [O\Expression::parameter('')], [O\Expression::argument(O\Expression::value(0))], [O\Expression::returnExpression()], [O\Expression::staticMethodCall(O\Expression::value(0), O\Expression::value(0))], [O\Expression::staticField(O\Expression::value(0), O\Expression::value(0))], [O\Expression::ternary(O\Expression::value(0), null, O\Expression::value(0))], [O\Expression::throwExpression(O\Expression::value(0))], [O\Expression::value(0)], [O\Expression::variable(O\Expression::value(0))], [O\Expression::constant('foo')], [O\Expression::classConstant(O\Expression::value(0), 'foo')]]; }
/** * @dataProvider parsers */ public function testAssignmentOperator() { $this->assertParsedAs([PowerOperators::TYPE, 'assignmentOperator'], [O\Expression::assign(O\Expression::variable(O\Expression::value('i')), O\Operators\Assignment::POWER, O\Expression::value(5))]); }
/** * @dataProvider parsers */ private function assertCast(callable $function, $typeOperator, $castName) { $this->assertParsedAs($function, [O\Expression::cast($typeOperator, O\Expression::variable(O\Expression::value($castName)))]); }
/** * @param callable $function * @param array $variableTypeMap * @param mixed $expression * * @return ITypeAnalysis */ protected function getAnalysis(callable $function, array $variableTypeMap = [], &$expression = null) { $reflection = $this->functionInterpreter->getReflection($function); foreach ($reflection->getSignature()->getParameterExpressions() as $parameterExpression) { $variableTypeMap[$parameterExpression->getName()] = $this->typeSystem->getTypeFromTypeHint($parameterExpression->getTypeHint()); } $analysisContext = $this->expressionAnalyser->createAnalysisContext($reflection->asEvaluationContext()); foreach ($variableTypeMap as $variable => $type) { $analysisContext->setExpressionType(O\Expression::variable(O\Expression::value($variable)), $type); } $bodyExpressions = $this->functionInterpreter->getStructure($reflection)->getBodyExpressions(); foreach ($bodyExpressions as $expression) { if ($expression instanceof O\ReturnExpression) { return $this->expressionAnalyser->analyse($analysisContext, $expression->getValue()); } elseif (count($bodyExpressions) === 1) { return $this->expressionAnalyser->analyse($analysisContext, $expression); } else { $this->expressionAnalyser->analyse($analysisContext, $expression); } } }
protected static function variable($name) { return O\Expression::variable(O\Expression::value($name)); }
/** * @dataProvider parsers */ public function testThatChainedMethodCalls() { $this->assertReturn(function (\Pinq\ITraversable $traversable) { return $traversable->asArray(); }, O\Expression::methodCall(O\Expression::variable(O\Expression::value('traversable')), O\Expression::value('asArray'))); $this->assertReturn(function (\Pinq\ITraversable $traversable) { return $traversable->where(function ($i) { return $i > 0; })->all(function ($i) { return $i % 2 === 0; }); }, O\Expression::methodCall(O\Expression::methodCall(O\Expression::variable(O\Expression::value('traversable')), O\Expression::value('where'), [O\Expression::argument(O\Expression::closure(false, false, [O\Expression::parameter('i')], [], [O\Expression::returnExpression(O\Expression::binaryOperation(O\Expression::variable(O\Expression::value('i')), O\Operators\Binary::GREATER_THAN, O\Expression::value(0)))]))]), O\Expression::value('all'), [O\Expression::argument(O\Expression::closure(false, false, [O\Expression::parameter('i')], [], [O\Expression::returnExpression(O\Expression::binaryOperation(O\Expression::binaryOperation(O\Expression::variable(O\Expression::value('i')), O\Operators\Binary::MODULUS, O\Expression::value(2)), O\Operators\Binary::IDENTITY, O\Expression::value(0)))]))])); }
/** * @backupGlobals enabled */ public function testParameterCollectionCanEvaluateSuperGlobalExpression() { $this->collection->addExpression(O\Expression::index(O\Expression::variable(O\Expression::value('_POST')), O\Expression::value('var')), ParameterHasher::valueType()); $_POST['var'] = [1, 2, 3]; $this->assertResolvesTo([[1, 2, 3]]); }
protected function exampleFromDocsQuery() { $rowExpression = O\Expression::variable(O\Expression::value('row')); return $this->scopeRequest([new Q\Segments\Filter(new Q\Functions\ElementProjection($this->parameter(), self::SCOPE_TYPE, self::SCOPE_NAMESPACE, [$this->parameter() => 'this'], [O\Expression::parameter('row')], [O\Expression::returnExpression(O\Expression::binaryOperation(O\Expression::index($rowExpression, O\Expression::value('age')), O\Operators\Binary::LESS_THAN_OR_EQUAL_TO, O\Expression::value(50)))])), new Q\Segments\OrderBy([new Q\Segments\Ordering($this->indexProjection('firstName'), $this->parameter()), new Q\Segments\Ordering($this->indexProjection('lastName'), $this->parameter())]), new Q\Segments\Range($this->parameter(), $this->parameter()), new Q\Segments\IndexBy($this->indexProjection('phoneNumber')), new Q\Segments\Select(new Q\Functions\ElementProjection($this->parameter(), self::SCOPE_TYPE, self::SCOPE_NAMESPACE, [$this->parameter() => 'this'], [O\Expression::parameter('row')], [O\Expression::returnExpression(O\Expression::arrayExpression([O\Expression::arrayItem(O\Expression::value('fullName'), O\Expression::binaryOperation(O\Expression::binaryOperation(O\Expression::index($rowExpression, O\Expression::value('firstName')), O\Operators\Binary::CONCATENATION, O\Expression::value(' ')), O\Operators\Binary::CONCATENATION, O\Expression::index($rowExpression, O\Expression::value('lastName')))), O\Expression::arrayItem(O\Expression::value('address'), O\Expression::index($rowExpression, O\Expression::value('address'))), O\Expression::arrayItem(O\Expression::value('dateOfBirth'), O\Expression::index($rowExpression, O\Expression::value('dateOfBirth')))]))]))]); }
public function testWithSpecialVariableNames() { $this->assertSame('1,2,3', O\CompiledEvaluator::fromExpressions([O\Expression::returnExpression(O\Expression::variable(O\Expression::value('a special var--')))], O\EvaluationContext::globalScope(null, ['a special var--' => '1,2,3']))->evaluate()); }