123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502 |
- #include "yql_expr_builder.h"
- #include "yql_expr.h"
- namespace NYql {
- TExprNodeBuilder::TExprNodeBuilder(TPositionHandle pos, TExprContext& ctx)
- : Ctx(ctx)
- , Parent(nullptr)
- , ParentReplacer(nullptr)
- , Container(nullptr)
- , Pos(pos)
- , CurrentNode(nullptr)
- {}
- TExprNodeBuilder::TExprNodeBuilder(TPositionHandle pos, TExprContext& ctx, ExtArgsFuncType extArgsFunc)
- : Ctx(ctx)
- , Parent(nullptr)
- , ParentReplacer(nullptr)
- , Container(nullptr)
- , Pos(pos)
- , CurrentNode(nullptr)
- , ExtArgsFunc(extArgsFunc)
- {}
- TExprNodeBuilder::TExprNodeBuilder(TPositionHandle pos, TExprNodeBuilder* parent, const TExprNode::TPtr& container)
- : Ctx(parent->Ctx)
- , Parent(parent)
- , ParentReplacer(nullptr)
- , Container(std::move(container))
- , Pos(pos)
- , CurrentNode(nullptr)
- {
- if (Parent) {
- ExtArgsFunc = Parent->ExtArgsFunc;
- }
- }
- TExprNodeBuilder::TExprNodeBuilder(TPositionHandle pos, TExprNodeReplaceBuilder* parentReplacer)
- : Ctx(parentReplacer->Owner->Ctx)
- , Parent(nullptr)
- , ParentReplacer(parentReplacer)
- , Container(nullptr)
- , Pos(pos)
- , CurrentNode(nullptr)
- {
- }
- TExprNode::TPtr TExprNodeBuilder::Build() {
- Y_ENSURE(CurrentNode, "No current node");
- Y_ENSURE(!Parent, "Build is allowed only on top level");
- if (CurrentNode->Type() == TExprNode::Lambda) {
- Y_ENSURE(CurrentNode->ChildrenSize() > 0U, "Lambda is not complete");
- }
- return CurrentNode;
- }
- TExprNodeBuilder& TExprNodeBuilder::Seal() {
- Y_ENSURE(Parent, "Seal is allowed only on non-top level");
- if (Container->Type() == TExprNode::Lambda) {
- if (CurrentNode) {
- Y_ENSURE(Container->ChildrenSize() == 1, "Lambda is already complete.");
- Container->Children_.emplace_back(std::move(CurrentNode));
- } else {
- Y_ENSURE(Container->ChildrenSize() > 0U, "Lambda isn't complete.");
- }
- }
- return *Parent;
- }
- TExprNodeReplaceBuilder& TExprNodeBuilder::Done() {
- Y_ENSURE(ParentReplacer, "Done is allowed only if parent is a replacer");
- Y_ENSURE(CurrentNode, "No current node");
- for (auto& body : ParentReplacer->Body)
- body = Ctx.ReplaceNode(std::move(body), ParentReplacer->CurrentNode ? *ParentReplacer->CurrentNode : *ParentReplacer->Args->Child(ParentReplacer->CurrentIndex), CurrentNode);
- return *ParentReplacer;
- }
- TExprNodeBuilder& TExprNodeBuilder::Atom(ui32 index, TPositionHandle pos, const TStringBuf& content, ui32 flags) {
- Y_ENSURE(Container && !Container->IsLambda(), "Container expected");
- Y_ENSURE(Container->ChildrenSize() == index,
- "Container position mismatch, expected: " << Container->ChildrenSize() <<
- ", actual: " << index);
- auto child = Ctx.NewAtom(pos, content, flags);
- Container->Children_.push_back(child);
- return *this;
- }
- TExprNodeBuilder& TExprNodeBuilder::Atom(TPositionHandle pos, const TStringBuf& content, ui32 flags) {
- Y_ENSURE(!Container || Container->IsLambda(), "No container expected");
- Y_ENSURE(!CurrentNode, "Node is already build");
- CurrentNode = Ctx.NewAtom(pos, content, flags);
- return *this;
- }
- TExprNodeBuilder& TExprNodeBuilder::Atom(ui32 index, const TStringBuf& content, ui32 flags) {
- return Atom(index, Pos, content, flags);
- }
- TExprNodeBuilder& TExprNodeBuilder::Atom(const TStringBuf& content, ui32 flags) {
- return Atom(Pos, content, flags);
- }
- TExprNodeBuilder& TExprNodeBuilder::Atom(ui32 index, ui32 literalIndexValue) {
- return Atom(index, Pos, Ctx.GetIndexAsString(literalIndexValue), TNodeFlags::Default);
- }
- TExprNodeBuilder& TExprNodeBuilder::Atom(ui32 literalIndexValue) {
- return Atom(Pos, Ctx.GetIndexAsString(literalIndexValue), TNodeFlags::Default);
- }
- TExprNodeBuilder TExprNodeBuilder::List(ui32 index, TPositionHandle pos) {
- Y_ENSURE(Container, "Container expected");
- Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
- "Container position mismatch, expected: " << Container->ChildrenSize() <<
- ", actual: " << index);
- const auto child = Ctx.NewList(pos, {});
- Container->Children_.push_back(child);
- return TExprNodeBuilder(pos, this, child);
- }
- TExprNodeBuilder TExprNodeBuilder::List(TPositionHandle pos) {
- Y_ENSURE(!Container || Container->Type() == TExprNode::Lambda, "No container expected");
- Y_ENSURE(!CurrentNode, "Node is already build");
- CurrentNode = Ctx.NewList(pos, {});
- return TExprNodeBuilder(pos, this, CurrentNode);
- }
- TExprNodeBuilder TExprNodeBuilder::List(ui32 index) {
- return List(index, Pos);
- }
- TExprNodeBuilder TExprNodeBuilder::List() {
- return List(Pos);
- }
- TExprNodeBuilder& TExprNodeBuilder::Add(ui32 index, const TExprNode::TPtr& child) {
- Y_ENSURE(Container, "Container expected");
- Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
- "Container position mismatch, expected: " << Container->ChildrenSize() <<
- ", actual: " << index);
- Y_ENSURE(child, "child should not be nullptr");
- Container->Children_.push_back(child);
- return *this;
- }
- TExprNodeBuilder& TExprNodeBuilder::Add(ui32 index, TExprNode::TPtr&& child) {
- Y_ENSURE(Container, "Container expected");
- Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
- "Container position mismatch, expected: " << Container->ChildrenSize() <<
- ", actual: " << index);
- Y_ENSURE(child, "child should not be nullptr");
- Container->Children_.push_back(std::move(child));
- return *this;
- }
- TExprNodeBuilder& TExprNodeBuilder::Add(TExprNode::TListType&& children) {
- Y_ENSURE(Container && Container->Type() != TExprNode::Lambda, "Container expected");
- Y_ENSURE(Container->Children_.empty(), "container should be empty");
- Container->Children_ = std::move(children);
- return *this;
- }
- TExprNodeBuilder& TExprNodeBuilder::Set(TExprNode::TPtr&& body) {
- Y_ENSURE(Container && Container->Type() == TExprNode::Lambda, "Lambda expected");
- Y_ENSURE(!CurrentNode, "Lambda already has a body");
- CurrentNode = std::move(body);
- return *this;
- }
- TExprNodeBuilder& TExprNodeBuilder::Set(const TExprNode::TPtr& body) {
- Y_ENSURE(Container && Container->Type() == TExprNode::Lambda, "Lambda expected");
- Y_ENSURE(!CurrentNode, "Lambda already has a body");
- CurrentNode = body;
- return *this;
- }
- TExprNodeBuilder TExprNodeBuilder::Callable(ui32 index, TPositionHandle pos, const TStringBuf& content) {
- Y_ENSURE(Container, "Container expected");
- Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
- "Container position mismatch, expected: " << Container->ChildrenSize() <<
- ", actual: " << index);
- auto child = Ctx.NewCallable(pos, content, {});
- Container->Children_.push_back(child);
- return TExprNodeBuilder(pos, this, child);
- }
- TExprNodeBuilder TExprNodeBuilder::Callable(TPositionHandle pos, const TStringBuf& content) {
- Y_ENSURE(!Container || Container->Type() == TExprNode::Lambda, "No container expected");
- Y_ENSURE(!CurrentNode, "Node is already build");
- CurrentNode = Ctx.NewCallable(pos, content, {});
- return TExprNodeBuilder(pos, this, CurrentNode);
- }
- TExprNodeBuilder TExprNodeBuilder::Callable(ui32 index, const TStringBuf& content) {
- return Callable(index, Pos, content);
- }
- TExprNodeBuilder TExprNodeBuilder::Callable(const TStringBuf& content) {
- return Callable(Pos, content);
- }
- TExprNodeBuilder& TExprNodeBuilder::World(ui32 index, TPositionHandle pos) {
- Y_ENSURE(Container, "Container expected");
- Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
- "Container position mismatch, expected: " << Container->ChildrenSize() <<
- ", actual: " << index);
- auto child = Ctx.NewWorld(pos);
- Container->Children_.push_back(child);
- return *this;
- }
- TExprNodeBuilder& TExprNodeBuilder::World(TPositionHandle pos) {
- Y_ENSURE(!Container, "No container expected");
- Y_ENSURE(!CurrentNode, "Node is already build");
- CurrentNode = Ctx.NewWorld(pos);
- return *this;
- }
- TExprNodeBuilder& TExprNodeBuilder::World(ui32 index) {
- return World(index, Pos);
- }
- TExprNodeBuilder& TExprNodeBuilder::World() {
- return World(Pos);
- }
- TExprNodeBuilder TExprNodeBuilder::Lambda(ui32 index, TPositionHandle pos) {
- Y_ENSURE(Container, "Container expected");
- Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
- "Container position mismatch, expected: " << Container->ChildrenSize() <<
- ", actual: " << index);
- auto child = Ctx.NewLambda(pos, Ctx.NewArguments(pos, {}), nullptr);
- Container->Children_.push_back(child);
- return TExprNodeBuilder(pos, this, child);
- }
- TExprNodeBuilder TExprNodeBuilder::Lambda(TPositionHandle pos) {
- Y_ENSURE(!Container || Container->Type() == TExprNode::Lambda, "No container expected");
- Y_ENSURE(!CurrentNode, "Node is already build");
- CurrentNode = Ctx.NewLambda(pos, Ctx.NewArguments(pos, {}), nullptr);
- return TExprNodeBuilder(pos, this, CurrentNode);
- }
- TExprNodeBuilder TExprNodeBuilder::Lambda(ui32 index) {
- return Lambda(index, Pos);
- }
- TExprNodeBuilder TExprNodeBuilder::Lambda() {
- return Lambda(Pos);
- }
- TExprNodeBuilder& TExprNodeBuilder::Param(TPositionHandle pos, const TStringBuf& name) {
- Y_ENSURE(!name.empty(), "Empty parameter name is not allowed");
- Y_ENSURE(Container, "Container expected");
- Y_ENSURE(Container->Type() == TExprNode::Lambda, "Container must be a lambda");
- Y_ENSURE(!CurrentNode, "Lambda already has a body");
- for (auto arg : Container->Head().Children()) {
- Y_ENSURE(arg->Content() != name, "Duplicate of lambda param name: " << name);
- }
- Container->Head().Children_.push_back(Ctx.NewArgument(pos, name));
- return *this;
- }
- TExprNodeBuilder& TExprNodeBuilder::Param(const TStringBuf& name) {
- return Param(Pos, name);
- }
- TExprNodeBuilder& TExprNodeBuilder::Params(const TStringBuf& name, ui32 width) {
- Y_ENSURE(!name.empty(), "Empty parameter name is not allowed");
- for (ui32 i = 0U; i < width; ++i)
- Param(Pos, TString(name) += ToString(i));
- return *this;
- }
- TExprNodeBuilder& TExprNodeBuilder::Arg(ui32 index, const TStringBuf& name) {
- Y_ENSURE(!name.empty(), "Empty parameter name is not allowed");
- Y_ENSURE(Container, "Container expected");
- Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
- "Container position mismatch, expected: " << Container->ChildrenSize() <<
- ", actual: " << index);
- auto arg = FindArgument(name);
- Container->Children_.push_back(arg);
- return *this;
- }
- TExprNodeBuilder& TExprNodeBuilder::Arg(const TStringBuf& name) {
- Y_ENSURE(!Container || Container->Type() == TExprNode::Lambda, "No container expected");
- Y_ENSURE(!CurrentNode, "Node is already build");
- CurrentNode = FindArgument(name);
- return *this;
- }
- TExprNodeBuilder& TExprNodeBuilder::Arg(ui32 index, const TStringBuf& name, ui32 toIndex) {
- Y_ENSURE(!name.empty(), "Empty parameter name is not allowed");
- return Arg(index, TString(name) += ToString(toIndex));
- }
- TExprNodeBuilder& TExprNodeBuilder::Arg(const TStringBuf& name, ui32 toIndex) {
- Y_ENSURE(!name.empty(), "Empty parameter name is not allowed");
- return Arg(TString(name) += ToString(toIndex));
- }
- TExprNodeBuilder& TExprNodeBuilder::Arg(const TExprNodePtr& arg) {
- Y_ENSURE(arg->Type() == TExprNode::Argument, "Argument expected");
- Y_ENSURE(!Container || Container->Type() == TExprNode::Lambda, "No container expected");
- Y_ENSURE(!CurrentNode, "Node is already build");
- CurrentNode = arg;
- return *this;
- }
- TExprNodeBuilder& TExprNodeBuilder::Args(ui32 index, const TStringBuf& name, ui32 toIndex) {
- Y_ENSURE(!name.empty(), "Empty parameter name is not allowed");
- for (auto i = 0U; index < toIndex; ++i)
- Arg(index++, TString(name) += ToString(i));
- return *this;
- }
- TExprNodeBuilder& TExprNodeBuilder::Args(const TStringBuf& name, ui32 toIndex) {
- Y_ENSURE(!name.empty(), "Empty parameter name is not allowed");
- for (auto i = 0U; i < toIndex; ++i)
- Arg(i, TString(name) += ToString(i));
- return *this;
- }
- TExprNode::TPtr TExprNodeBuilder::FindArgument(const TStringBuf& name) {
- for (auto builder = this; builder; builder = builder->Parent) {
- while (builder->ParentReplacer) {
- builder = builder->ParentReplacer->Owner;
- }
- if (builder->Container && builder->Container->IsLambda()) {
- for (const auto& arg : builder->Container->Head().Children()) {
- if (arg->Content() == name) {
- return arg;
- }
- }
- }
- }
- if (ExtArgsFunc) {
- if (const auto arg = ExtArgsFunc(name)) {
- return arg;
- }
- }
- ythrow yexception() << "Parameter not found: " << name;
- }
- TExprNodeReplaceBuilder TExprNodeBuilder::Apply(ui32 index, const TExprNode& lambda) {
- Y_ENSURE(Container, "Container expected");
- Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
- "Container position mismatch, expected: " << Container->ChildrenSize() <<
- ", actual: " << index);
- return TExprNodeReplaceBuilder(this, Container, lambda.HeadPtr(), GetLambdaBody(lambda));
- }
- TExprNodeReplaceBuilder TExprNodeBuilder::Apply(const TExprNode& lambda) {
- Y_ENSURE(!Container || Container->Type() == TExprNode::Lambda, "No container expected");
- Y_ENSURE(!CurrentNode, "Node is already build");
- return TExprNodeReplaceBuilder(this, Container, lambda.HeadPtr(), GetLambdaBody(lambda));
- }
- TExprNodeReplaceBuilder TExprNodeBuilder::Apply(ui32 index, const TExprNode::TPtr& lambda) {
- return Apply(index, *lambda);
- }
- TExprNodeReplaceBuilder TExprNodeBuilder::Apply(const TExprNode::TPtr& lambda) {
- return Apply(*lambda);
- }
- TExprNodeReplaceBuilder TExprNodeBuilder::ApplyPartial(ui32 index, TExprNode::TPtr args, TExprNode::TPtr body) {
- Y_ENSURE(Container, "Container expected");
- Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
- "Container position mismatch, expected: " << Container->ChildrenSize() <<
- ", actual: " << index);
- Y_ENSURE(!args || args->IsArguments());
- return TExprNodeReplaceBuilder(this, Container, std::move(args), std::move(body));
- }
- TExprNodeReplaceBuilder TExprNodeBuilder::ApplyPartial(ui32 index, TExprNode::TPtr args, TExprNode::TListType body) {
- Y_ENSURE(Container, "Container expected");
- Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
- "Container position mismatch, expected: " << Container->ChildrenSize() <<
- ", actual: " << index);
- Y_ENSURE(!args || args->IsArguments());
- return TExprNodeReplaceBuilder(this, Container, std::move(args), std::move(body));
- }
- TExprNodeReplaceBuilder TExprNodeBuilder::ApplyPartial(TExprNode::TPtr args, TExprNode::TPtr body) {
- Y_ENSURE(!Container || Container->Type() == TExprNode::Lambda, "No container expected");
- Y_ENSURE(!CurrentNode, "Node is already build");
- Y_ENSURE(!args || args->IsArguments());
- return TExprNodeReplaceBuilder(this, Container, std::move(args), std::move(body));
- }
- TExprNodeReplaceBuilder TExprNodeBuilder::ApplyPartial(TExprNode::TPtr args, TExprNode::TListType body) {
- Y_ENSURE(!Container || Container->Type() == TExprNode::Lambda, "No container expected");
- Y_ENSURE(!CurrentNode, "Node is already build");
- Y_ENSURE(!args || args->IsArguments());
- return TExprNodeReplaceBuilder(this, Container, std::move(args), std::move(body));
- }
- TExprNodeReplaceBuilder::TExprNodeReplaceBuilder(TExprNodeBuilder* owner, TExprNode::TPtr container,
- TExprNode::TPtr&& args, TExprNode::TPtr&& body)
- : Owner(owner)
- , Container(std::move(container))
- , Args(std::move(args))
- , Body({std::move(body)})
- , CurrentIndex(0)
- , CurrentNode(nullptr)
- {
- }
- TExprNodeReplaceBuilder::TExprNodeReplaceBuilder(TExprNodeBuilder* owner, TExprNode::TPtr container,
- TExprNode::TPtr&& args, TExprNode::TListType&& body)
- : Owner(owner)
- , Container(std::move(container))
- , Args(std::move(args))
- , Body(std::move(body))
- , CurrentIndex(0)
- , CurrentNode(nullptr)
- {
- }
- TExprNodeReplaceBuilder::TExprNodeReplaceBuilder(TExprNodeBuilder* owner, TExprNode::TPtr container,
- const TExprNode& lambda)
- : TExprNodeReplaceBuilder(owner, std::move(container), lambda.HeadPtr(), lambda.TailPtr())
- {
- Y_ENSURE(lambda.Type() == TExprNode::Lambda, "Expected lambda");
- }
- TExprNodeReplaceBuilder& TExprNodeReplaceBuilder::With(
- ui32 argIndex, const TStringBuf& toName) {
- Y_ENSURE(Args, "No arguments");
- Y_ENSURE(argIndex < Args->ChildrenSize(), "Wrong argument index");
- Body = Owner->Ctx.ReplaceNodes(std::move(Body), {{Args->Child(argIndex), Owner->FindArgument(toName)}});
- return *this;
- }
- TExprNodeReplaceBuilder& TExprNodeReplaceBuilder::With(
- ui32 argIndex, TExprNode::TPtr toNode) {
- Y_ENSURE(Args, "No arguments");
- Y_ENSURE(argIndex < Args->ChildrenSize(), "Wrong argument index");
- Body = Owner->Ctx.ReplaceNodes(std::move(Body), {{Args->Child(argIndex), std::move(toNode)}});
- return *this;
- }
- TExprNodeReplaceBuilder& TExprNodeReplaceBuilder::With(const TStringBuf& toName) {
- Y_ENSURE(Args, "No arguments");
- Y_ENSURE(!toName.empty(), "Empty parameter name is not allowed");
- TNodeOnNodeOwnedMap replaces(Args->ChildrenSize());
- for (ui32 i = 0U; i < Args->ChildrenSize(); ++i)
- Y_ENSURE(replaces.emplace(Args->Child(i), Owner->FindArgument(TString(toName) += ToString(i))).second, "Must be uinique.");
- Body = Owner->Ctx.ReplaceNodes(std::move(Body), replaces);
- return *this;
- }
- TExprNodeReplaceBuilder& TExprNodeReplaceBuilder::With(const TStringBuf& toName, ui32 toIndex) {
- Y_ENSURE(!toName.empty(), "Empty parameter name is not allowed");
- return With(TString(toName) += ToString(toIndex));
- }
- TExprNodeReplaceBuilder& TExprNodeReplaceBuilder::With(ui32 argIndex, const TStringBuf& toName, ui32 toIndex) {
- Y_ENSURE(!toName.empty(), "Empty parameter name is not allowed");
- return With(argIndex, TString(toName) += ToString(toIndex));
- }
- TExprNodeReplaceBuilder& TExprNodeReplaceBuilder::WithNode(const TExprNode& fromNode, TExprNode::TPtr&& toNode) {
- Body = Owner->Ctx.ReplaceNodes(std::move(Body), {{&fromNode, std::move(toNode)}});
- return *this;
- }
- TExprNodeReplaceBuilder& TExprNodeReplaceBuilder::WithNode(const TExprNode& fromNode, const TStringBuf& toName) {
- return WithNode(fromNode, Owner->FindArgument(toName));
- }
- TExprNodeBuilder TExprNodeReplaceBuilder::With(ui32 argIndex) {
- CurrentIndex = argIndex;
- return TExprNodeBuilder(Owner->Pos, this);
- }
- TExprNodeBuilder TExprNodeReplaceBuilder::WithNode(TExprNode::TPtr&& fromNode) {
- CurrentNode = std::move(fromNode);
- return TExprNodeBuilder(Owner->Pos, this);
- }
- TExprNodeBuilder& TExprNodeReplaceBuilder::Seal() {
- if (Container) {
- std::move(Body.begin(), Body.end(), std::back_inserter(Container->Children_));
- } else {
- Y_ENSURE(1U == Body.size() && Body.front(), "Expected single node.");
- Owner->CurrentNode = std::move(Body.front());
- }
- Body.clear();
- return *Owner;
- }
- } // namespace NYql
|