Author: Elliot Levin (elliotlevin@hotmail.com)
Inheritance: extends Expression
 public function getCallable()
 {
     if ($this->callable === null) {
         $this->callable = $this->expression->evaluate($this->evaluationContext);
     }
     return $this->callable;
 }
 public function visitClosure(O\ClosureExpression $expression)
 {
     $originalContext = $this->analysisContext;
     $this->analysisContext = $originalContext->inNewScope();
     foreach ($expression->getParameters() as $parameter) {
         $this->walk($parameter);
         $typeHintType = $this->typeSystem->getTypeFromTypeHint($parameter->getTypeHint());
         if (!$parameter->hasDefaultValue() || $this->analysis[$parameter->getDefaultValue()]->isEqualTo($typeHintType)) {
             $this->analysisContext->setExpressionType($parameter->asVariable(), $typeHintType);
         } else {
             $this->analysisContext->setExpressionType($parameter->asVariable(), $this->typeSystem->getNativeType(INativeType::TYPE_MIXED));
         }
     }
     foreach ($expression->getUsedVariables() as $usedVariable) {
         $variable = $usedVariable->asVariable();
         //TODO: handle references with used variables. Probably impossible though.
         $this->analysisContext->setExpressionType($variable, $originalContext->getExpressionType($variable));
     }
     $this->walkAll($expression->getBodyExpressions());
     $this->analysis[$expression] = $this->typeSystem->getObjectType('Closure');
     $this->analysisContext = $originalContext;
 }
 protected function parseQueryExpression(callable $queryFunction, O\IEvaluationContext &$evaluationContext = null)
 {
     $reflection = $this->functionInterpreter->getReflection($queryFunction);
     $evaluationContext = $reflection->asEvaluationContext();
     $function = $this->functionInterpreter->getStructure($reflection);
     $expressions = $function->getBodyExpressions();
     $this->assertCount(1, $expressions);
     //Resolve the parameter variable with the queryable value and $this
     $parameterName = $reflection->getSignature()->getParameterExpressions()[0]->getName();
     $expression = $expressions[0];
     foreach ([$parameterName => $this->queryable, 'this' => $this] as $variable => $value) {
         $variableReplacer = new O\DynamicExpressionWalker([O\VariableExpression::getType() => function (O\VariableExpression $expression) use($variable, &$value) {
             if ($expression->getName() instanceof O\ValueExpression && $expression->getName()->getValue() === $variable) {
                 return O\Expression::value($value);
             } else {
                 return $expression;
             }
         }, O\ClosureExpression::getType() => function ($closure) {
             return $closure;
         }]);
         $expression = $variableReplacer->walk($expression);
     }
     if ($expression instanceof O\ReturnExpression) {
         return $expression->getValue();
     } else {
         return $expression;
     }
 }