src/Execution/Reducer.php
protected function walkQuery($queryNode, FieldInterface $currentLevelAST)
    {
        $childrenScore = 0;
        if (!($queryNode instanceof FieldAst)) {
            foreach ($queryNode->getFields() as $queryField) {
                if ($queryField instanceof FragmentInterface) {
                    if ($queryField instanceof FragmentReference) {
                        $queryField = $this->executionContext->getRequest()->getFragment($queryField->getName());
                    }
                    // the next 7 lines are essentially equivalent to `yield from $this->walkQuery(...)` in PHP7.
                    // for backwards compatibility this is equivalent.
                    // This pattern is repeated multiple times in this function, and unfortunately cannot be extracted or
                    // made less verbose.
                    $gen  = $this->walkQuery($queryField, $currentLevelAST);
                    $next = $gen->current();
                    while ($next) {
                        $received = (yield $next);
                        $childrenScore += (int)$received;
                        $next = $gen->send($received);
                    }
                } else {
                    $fieldType = $currentLevelAST->getType()->getNamedType();
                    if ($fieldType instanceof AbstractUnionType) {
                        foreach ($fieldType->getTypes() as $unionFieldType) {
                            if ($fieldAst = $unionFieldType->getField($queryField->getName())) {
                                $gen  = $this->walkQuery($queryField, $fieldAst);
                                $next = $gen->current();
                                while ($next) {
                                    $received = (yield $next);
                                    $childrenScore += (int)$received;
                                    $next = $gen->send($received);
                                }
                            }
                        }
                    } elseif ($fieldType instanceof AbstractObjectType && $fieldAst = $fieldType->getField($queryField->getName())) {
                        $gen  = $this->walkQuery($queryField, $fieldAst);
                        $next = $gen->current();
                        while ($next) {
                            $received = (yield $next);
                            $childrenScore += (int)$received;
                            $next = $gen->send($received);
                        }
                    }
                }
            }
        }
        // sanity check.  don't yield fragments; they don't contribute to cost
        if ($queryNode instanceof Query || $queryNode instanceof FieldAst) {
            // BASE CASE.  If we're here we're done recursing -
            // this node is either a field, or a query that we've finished recursing into.
            yield [$queryNode, $currentLevelAST, $childrenScore];
        }
    }
protected function walkQuery($queryNode, FieldInterface $currentLevelAST)
    {
        $childrenScore = 0;
        if (!($queryNode instanceof FieldAst)) {
            foreach ($queryNode->getFields() as $queryField) {
                if ($queryField instanceof FragmentInterface) {
                    if ($queryField instanceof FragmentReference) {
                        $queryField = $this->executionContext->getRequest()->getFragment($queryField->getName());
                    }
                    // the next 7 lines are essentially equivalent to `yield from $this->walkQuery(...)` in PHP7.
                    // for backwards compatibility this is equivalent.
                    // This pattern is repeated multiple times in this function, and unfortunately cannot be extracted or
                    // made less verbose.
                    $gen  = $this->walkQuery($queryField, $currentLevelAST);
                    $next = $gen->current();
                    while ($next) {
                        $received = (yield $next);
                        $childrenScore += (int)$received;
                        $next = $gen->send($received);
                    }
                } else {
                    $fieldType = $currentLevelAST->getType()->getNamedType();
                    if ($fieldType instanceof AbstractUnionType) {
                        foreach ($fieldType->getTypes() as $unionFieldType) {
                            if ($fieldAst = $unionFieldType->getField($queryField->getName())) {
                                $gen  = $this->walkQuery($queryField, $fieldAst);
                                $next = $gen->current();
                                while ($next) {
                                    $received = (yield $next);
                                    $childrenScore += (int)$received;
                                    $next = $gen->send($received);
                                }
                            }
                        }
                    } elseif ($fieldType instanceof AbstractObjectType && $fieldAst = $fieldType->getField($queryField->getName())) {
                        $gen  = $this->walkQuery($queryField, $fieldAst);
                        $next = $gen->current();
                        while ($next) {
                            $received = (yield $next);
                            $childrenScore += (int)$received;
                            $next = $gen->send($received);
                        }
                    }
                }
            }
        }
        // sanity check.  don't yield fragments; they don't contribute to cost
        if ($queryNode instanceof Query || $queryNode instanceof FieldAst) {
            // BASE CASE.  If we're here we're done recursing -
            // this node is either a field, or a query that we've finished recursing into.
            yield [$queryNode, $currentLevelAST, $childrenScore];
        }
    }
Coroutine to walk the query and schema in DFS manner (see AbstractQueryVisitor docs for more info) and yield a
tuple of (queryNode, schemaNode, childScore)

childScore costs are accumulated via values sent into the coroutine.

Most of the branching in this function is just to handle the different types in a query: Queries, Unions,
Fragments (anonymous and named), and Fields.  The core of the function is simple: recurse until we hit the base
case of a Field and yield that back up to the visitor up in `doVisit`.

@param Query|Field|\Youshido\GraphQL\Parser\Ast\Interfaces\FragmentInterface $queryNode
@param FieldInterface                                                        $currentLevelAST

@return \Generator