std::pair<std::shared_ptr<Node>, boost::optional<Status>> createNode(const Status& originalStatus, Point p, Point d, const std::shared_ptr<Node>& base, NodeFactory& nodeFactory, const HeurCalculator& heurCalculator, const Checker& checker, Dumper* dumper) { Point pd = p+d, pmd = p-d; if (originalStatus.value(pd) != FieldType::floor || !originalStatus.reachable(pmd)) { return {}; } Status status(originalStatus); status.currentPos(p); if (heurCalculator.calculateStone(status, pd) < 0 || !status.moveStone(p, pd)) { return {}; } auto doCreateNode = [&]() { return nodeFactory.createNode( status, MoveDescriptor(p, d), base); }; if (pd != status.table().destination()) { if (!checker.check(status, pd)) { if (dumper) { dumper->reject(doCreateNode(), checker.errorMessage()); } return {}; } } return {doCreateNode(), std::move(status)}; }
NodePointer Demangle::stripGenericArgsFromContextNode(NodePointer node, NodeFactory &factory) { switch (node->getKind()) { case Demangle::Node::Kind::BoundGenericClass: case Demangle::Node::Kind::BoundGenericEnum: case Demangle::Node::Kind::BoundGenericStructure: case Demangle::Node::Kind::BoundGenericOtherNominalType: // Bound generic types have a 'Type' node under them, whose child is // the non-generic reference. If we don't see that structure, do nothing. if (node->getNumChildren() < 2 || node->getChild(0)->getKind() != Demangle::Node::Kind::Type || node->getChild(0)->getNumChildren() < 1) return node; // Strip generic arguments from that child, then return it. return stripGenericArgsFromContextNode(node->getChild(0)->getChild(0), factory); case Demangle::Node::Kind::Class: case Demangle::Node::Kind::Enum: case Demangle::Node::Kind::Structure: case Demangle::Node::Kind::OtherNominalType: { if (node->getNumChildren() < 2) return node; auto newContext = stripGenericArgsFromContextNode(node->getChild(0), factory); if (newContext == node->getChild(0)) return node; auto newNode = factory.createNode(node->getKind()); newNode->addChild(newContext, factory); for (unsigned i = 1, n = node->getNumChildren(); i != n; ++i) newNode->addChild(node->getChild(i), factory); return newNode; } case Demangle::Node::Kind::Extension: { // Strip generic arguments from the extended type. if (node->getNumChildren() < 2) return node; auto newExtended = stripGenericArgsFromContextNode(node->getChild(1), factory); if (newExtended == node->getChild(1)) return node; auto newNode = factory.createNode(Node::Kind::Extension); newNode->addChild(node->getChild(0), factory); newNode->addChild(newExtended, factory); if (node->getNumChildren() == 3) newNode->addChild(node->getChild(2), factory); return newNode; } case Demangle::Node::Kind::Module: // Modules terminate the recursion. return node; default: // FIXME: Handle local contexts. return node; } }