yql_expr_builder.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. #include "yql_expr_builder.h"
  2. #include "yql_expr.h"
  3. namespace NYql {
  4. TExprNodeBuilder::TExprNodeBuilder(TPositionHandle pos, TExprContext& ctx)
  5. : Ctx(ctx)
  6. , Parent(nullptr)
  7. , ParentReplacer(nullptr)
  8. , Container(nullptr)
  9. , Pos(pos)
  10. , CurrentNode(nullptr)
  11. {}
  12. TExprNodeBuilder::TExprNodeBuilder(TPositionHandle pos, TExprContext& ctx, ExtArgsFuncType extArgsFunc)
  13. : Ctx(ctx)
  14. , Parent(nullptr)
  15. , ParentReplacer(nullptr)
  16. , Container(nullptr)
  17. , Pos(pos)
  18. , CurrentNode(nullptr)
  19. , ExtArgsFunc(extArgsFunc)
  20. {}
  21. TExprNodeBuilder::TExprNodeBuilder(TPositionHandle pos, TExprNodeBuilder* parent, const TExprNode::TPtr& container)
  22. : Ctx(parent->Ctx)
  23. , Parent(parent)
  24. , ParentReplacer(nullptr)
  25. , Container(std::move(container))
  26. , Pos(pos)
  27. , CurrentNode(nullptr)
  28. {
  29. if (Parent) {
  30. ExtArgsFunc = Parent->ExtArgsFunc;
  31. }
  32. }
  33. TExprNodeBuilder::TExprNodeBuilder(TPositionHandle pos, TExprNodeReplaceBuilder* parentReplacer)
  34. : Ctx(parentReplacer->Owner->Ctx)
  35. , Parent(nullptr)
  36. , ParentReplacer(parentReplacer)
  37. , Container(nullptr)
  38. , Pos(pos)
  39. , CurrentNode(nullptr)
  40. {
  41. }
  42. TExprNode::TPtr TExprNodeBuilder::Build() {
  43. Y_ENSURE(CurrentNode, "No current node");
  44. Y_ENSURE(!Parent, "Build is allowed only on top level");
  45. if (CurrentNode->Type() == TExprNode::Lambda) {
  46. Y_ENSURE(CurrentNode->ChildrenSize() > 0U, "Lambda is not complete");
  47. }
  48. return CurrentNode;
  49. }
  50. TExprNodeBuilder& TExprNodeBuilder::Seal() {
  51. Y_ENSURE(Parent, "Seal is allowed only on non-top level");
  52. if (Container->Type() == TExprNode::Lambda) {
  53. if (CurrentNode) {
  54. Y_ENSURE(Container->ChildrenSize() == 1, "Lambda is already complete.");
  55. Container->Children_.emplace_back(std::move(CurrentNode));
  56. } else {
  57. Y_ENSURE(Container->ChildrenSize() > 0U, "Lambda isn't complete.");
  58. }
  59. }
  60. return *Parent;
  61. }
  62. TExprNodeReplaceBuilder& TExprNodeBuilder::Done() {
  63. Y_ENSURE(ParentReplacer, "Done is allowed only if parent is a replacer");
  64. Y_ENSURE(CurrentNode, "No current node");
  65. for (auto& body : ParentReplacer->Body)
  66. body = Ctx.ReplaceNode(std::move(body), ParentReplacer->CurrentNode ? *ParentReplacer->CurrentNode : *ParentReplacer->Args->Child(ParentReplacer->CurrentIndex), CurrentNode);
  67. return *ParentReplacer;
  68. }
  69. TExprNodeBuilder& TExprNodeBuilder::Atom(ui32 index, TPositionHandle pos, const TStringBuf& content, ui32 flags) {
  70. Y_ENSURE(Container && !Container->IsLambda(), "Container expected");
  71. Y_ENSURE(Container->ChildrenSize() == index,
  72. "Container position mismatch, expected: " << Container->ChildrenSize() <<
  73. ", actual: " << index);
  74. auto child = Ctx.NewAtom(pos, content, flags);
  75. Container->Children_.push_back(child);
  76. return *this;
  77. }
  78. TExprNodeBuilder& TExprNodeBuilder::Atom(TPositionHandle pos, const TStringBuf& content, ui32 flags) {
  79. Y_ENSURE(!Container || Container->IsLambda(), "No container expected");
  80. Y_ENSURE(!CurrentNode, "Node is already build");
  81. CurrentNode = Ctx.NewAtom(pos, content, flags);
  82. return *this;
  83. }
  84. TExprNodeBuilder& TExprNodeBuilder::Atom(ui32 index, const TStringBuf& content, ui32 flags) {
  85. return Atom(index, Pos, content, flags);
  86. }
  87. TExprNodeBuilder& TExprNodeBuilder::Atom(const TStringBuf& content, ui32 flags) {
  88. return Atom(Pos, content, flags);
  89. }
  90. TExprNodeBuilder& TExprNodeBuilder::Atom(ui32 index, ui32 literalIndexValue) {
  91. return Atom(index, Pos, Ctx.GetIndexAsString(literalIndexValue), TNodeFlags::Default);
  92. }
  93. TExprNodeBuilder& TExprNodeBuilder::Atom(ui32 literalIndexValue) {
  94. return Atom(Pos, Ctx.GetIndexAsString(literalIndexValue), TNodeFlags::Default);
  95. }
  96. TExprNodeBuilder TExprNodeBuilder::List(ui32 index, TPositionHandle pos) {
  97. Y_ENSURE(Container, "Container expected");
  98. Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
  99. "Container position mismatch, expected: " << Container->ChildrenSize() <<
  100. ", actual: " << index);
  101. const auto child = Ctx.NewList(pos, {});
  102. Container->Children_.push_back(child);
  103. return TExprNodeBuilder(pos, this, child);
  104. }
  105. TExprNodeBuilder TExprNodeBuilder::List(TPositionHandle pos) {
  106. Y_ENSURE(!Container || Container->Type() == TExprNode::Lambda, "No container expected");
  107. Y_ENSURE(!CurrentNode, "Node is already build");
  108. CurrentNode = Ctx.NewList(pos, {});
  109. return TExprNodeBuilder(pos, this, CurrentNode);
  110. }
  111. TExprNodeBuilder TExprNodeBuilder::List(ui32 index) {
  112. return List(index, Pos);
  113. }
  114. TExprNodeBuilder TExprNodeBuilder::List() {
  115. return List(Pos);
  116. }
  117. TExprNodeBuilder& TExprNodeBuilder::Add(ui32 index, const TExprNode::TPtr& child) {
  118. Y_ENSURE(Container, "Container expected");
  119. Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
  120. "Container position mismatch, expected: " << Container->ChildrenSize() <<
  121. ", actual: " << index);
  122. Y_ENSURE(child, "child should not be nullptr");
  123. Container->Children_.push_back(child);
  124. return *this;
  125. }
  126. TExprNodeBuilder& TExprNodeBuilder::Add(ui32 index, TExprNode::TPtr&& child) {
  127. Y_ENSURE(Container, "Container expected");
  128. Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
  129. "Container position mismatch, expected: " << Container->ChildrenSize() <<
  130. ", actual: " << index);
  131. Y_ENSURE(child, "child should not be nullptr");
  132. Container->Children_.push_back(std::move(child));
  133. return *this;
  134. }
  135. TExprNodeBuilder& TExprNodeBuilder::Add(TExprNode::TListType&& children) {
  136. Y_ENSURE(Container && Container->Type() != TExprNode::Lambda, "Container expected");
  137. Y_ENSURE(Container->Children_.empty(), "container should be empty");
  138. Container->Children_ = std::move(children);
  139. return *this;
  140. }
  141. TExprNodeBuilder& TExprNodeBuilder::Set(TExprNode::TPtr&& body) {
  142. Y_ENSURE(Container && Container->Type() == TExprNode::Lambda, "Lambda expected");
  143. Y_ENSURE(!CurrentNode, "Lambda already has a body");
  144. CurrentNode = std::move(body);
  145. return *this;
  146. }
  147. TExprNodeBuilder& TExprNodeBuilder::Set(const TExprNode::TPtr& body) {
  148. Y_ENSURE(Container && Container->Type() == TExprNode::Lambda, "Lambda expected");
  149. Y_ENSURE(!CurrentNode, "Lambda already has a body");
  150. CurrentNode = body;
  151. return *this;
  152. }
  153. TExprNodeBuilder TExprNodeBuilder::Callable(ui32 index, TPositionHandle pos, const TStringBuf& content) {
  154. Y_ENSURE(Container, "Container expected");
  155. Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
  156. "Container position mismatch, expected: " << Container->ChildrenSize() <<
  157. ", actual: " << index);
  158. auto child = Ctx.NewCallable(pos, content, {});
  159. Container->Children_.push_back(child);
  160. return TExprNodeBuilder(pos, this, child);
  161. }
  162. TExprNodeBuilder TExprNodeBuilder::Callable(TPositionHandle pos, const TStringBuf& content) {
  163. Y_ENSURE(!Container || Container->Type() == TExprNode::Lambda, "No container expected");
  164. Y_ENSURE(!CurrentNode, "Node is already build");
  165. CurrentNode = Ctx.NewCallable(pos, content, {});
  166. return TExprNodeBuilder(pos, this, CurrentNode);
  167. }
  168. TExprNodeBuilder TExprNodeBuilder::Callable(ui32 index, const TStringBuf& content) {
  169. return Callable(index, Pos, content);
  170. }
  171. TExprNodeBuilder TExprNodeBuilder::Callable(const TStringBuf& content) {
  172. return Callable(Pos, content);
  173. }
  174. TExprNodeBuilder& TExprNodeBuilder::World(ui32 index, TPositionHandle pos) {
  175. Y_ENSURE(Container, "Container expected");
  176. Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
  177. "Container position mismatch, expected: " << Container->ChildrenSize() <<
  178. ", actual: " << index);
  179. auto child = Ctx.NewWorld(pos);
  180. Container->Children_.push_back(child);
  181. return *this;
  182. }
  183. TExprNodeBuilder& TExprNodeBuilder::World(TPositionHandle pos) {
  184. Y_ENSURE(!Container, "No container expected");
  185. Y_ENSURE(!CurrentNode, "Node is already build");
  186. CurrentNode = Ctx.NewWorld(pos);
  187. return *this;
  188. }
  189. TExprNodeBuilder& TExprNodeBuilder::World(ui32 index) {
  190. return World(index, Pos);
  191. }
  192. TExprNodeBuilder& TExprNodeBuilder::World() {
  193. return World(Pos);
  194. }
  195. TExprNodeBuilder TExprNodeBuilder::Lambda(ui32 index, TPositionHandle pos) {
  196. Y_ENSURE(Container, "Container expected");
  197. Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
  198. "Container position mismatch, expected: " << Container->ChildrenSize() <<
  199. ", actual: " << index);
  200. auto child = Ctx.NewLambda(pos, Ctx.NewArguments(pos, {}), nullptr);
  201. Container->Children_.push_back(child);
  202. return TExprNodeBuilder(pos, this, child);
  203. }
  204. TExprNodeBuilder TExprNodeBuilder::Lambda(TPositionHandle pos) {
  205. Y_ENSURE(!Container || Container->Type() == TExprNode::Lambda, "No container expected");
  206. Y_ENSURE(!CurrentNode, "Node is already build");
  207. CurrentNode = Ctx.NewLambda(pos, Ctx.NewArguments(pos, {}), nullptr);
  208. return TExprNodeBuilder(pos, this, CurrentNode);
  209. }
  210. TExprNodeBuilder TExprNodeBuilder::Lambda(ui32 index) {
  211. return Lambda(index, Pos);
  212. }
  213. TExprNodeBuilder TExprNodeBuilder::Lambda() {
  214. return Lambda(Pos);
  215. }
  216. TExprNodeBuilder& TExprNodeBuilder::Param(TPositionHandle pos, const TStringBuf& name) {
  217. Y_ENSURE(!name.empty(), "Empty parameter name is not allowed");
  218. Y_ENSURE(Container, "Container expected");
  219. Y_ENSURE(Container->Type() == TExprNode::Lambda, "Container must be a lambda");
  220. Y_ENSURE(!CurrentNode, "Lambda already has a body");
  221. for (auto arg : Container->Head().Children()) {
  222. Y_ENSURE(arg->Content() != name, "Duplicate of lambda param name: " << name);
  223. }
  224. Container->Head().Children_.push_back(Ctx.NewArgument(pos, name));
  225. return *this;
  226. }
  227. TExprNodeBuilder& TExprNodeBuilder::Param(const TStringBuf& name) {
  228. return Param(Pos, name);
  229. }
  230. TExprNodeBuilder& TExprNodeBuilder::Params(const TStringBuf& name, ui32 width) {
  231. Y_ENSURE(!name.empty(), "Empty parameter name is not allowed");
  232. for (ui32 i = 0U; i < width; ++i)
  233. Param(Pos, TString(name) += ToString(i));
  234. return *this;
  235. }
  236. TExprNodeBuilder& TExprNodeBuilder::Arg(ui32 index, const TStringBuf& name) {
  237. Y_ENSURE(!name.empty(), "Empty parameter name is not allowed");
  238. Y_ENSURE(Container, "Container expected");
  239. Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
  240. "Container position mismatch, expected: " << Container->ChildrenSize() <<
  241. ", actual: " << index);
  242. auto arg = FindArgument(name);
  243. Container->Children_.push_back(arg);
  244. return *this;
  245. }
  246. TExprNodeBuilder& TExprNodeBuilder::Arg(const TStringBuf& name) {
  247. Y_ENSURE(!Container || Container->Type() == TExprNode::Lambda, "No container expected");
  248. Y_ENSURE(!CurrentNode, "Node is already build");
  249. CurrentNode = FindArgument(name);
  250. return *this;
  251. }
  252. TExprNodeBuilder& TExprNodeBuilder::Arg(ui32 index, const TStringBuf& name, ui32 toIndex) {
  253. Y_ENSURE(!name.empty(), "Empty parameter name is not allowed");
  254. return Arg(index, TString(name) += ToString(toIndex));
  255. }
  256. TExprNodeBuilder& TExprNodeBuilder::Arg(const TStringBuf& name, ui32 toIndex) {
  257. Y_ENSURE(!name.empty(), "Empty parameter name is not allowed");
  258. return Arg(TString(name) += ToString(toIndex));
  259. }
  260. TExprNodeBuilder& TExprNodeBuilder::Arg(const TExprNodePtr& arg) {
  261. Y_ENSURE(arg->Type() == TExprNode::Argument, "Argument expected");
  262. Y_ENSURE(!Container || Container->Type() == TExprNode::Lambda, "No container expected");
  263. Y_ENSURE(!CurrentNode, "Node is already build");
  264. CurrentNode = arg;
  265. return *this;
  266. }
  267. TExprNodeBuilder& TExprNodeBuilder::Args(ui32 index, const TStringBuf& name, ui32 toIndex) {
  268. Y_ENSURE(!name.empty(), "Empty parameter name is not allowed");
  269. for (auto i = 0U; index < toIndex; ++i)
  270. Arg(index++, TString(name) += ToString(i));
  271. return *this;
  272. }
  273. TExprNodeBuilder& TExprNodeBuilder::Args(const TStringBuf& name, ui32 toIndex) {
  274. Y_ENSURE(!name.empty(), "Empty parameter name is not allowed");
  275. for (auto i = 0U; i < toIndex; ++i)
  276. Arg(i, TString(name) += ToString(i));
  277. return *this;
  278. }
  279. TExprNode::TPtr TExprNodeBuilder::FindArgument(const TStringBuf& name) {
  280. for (auto builder = this; builder; builder = builder->Parent) {
  281. while (builder->ParentReplacer) {
  282. builder = builder->ParentReplacer->Owner;
  283. }
  284. if (builder->Container && builder->Container->IsLambda()) {
  285. for (const auto& arg : builder->Container->Head().Children()) {
  286. if (arg->Content() == name) {
  287. return arg;
  288. }
  289. }
  290. }
  291. }
  292. if (ExtArgsFunc) {
  293. if (const auto arg = ExtArgsFunc(name)) {
  294. return arg;
  295. }
  296. }
  297. ythrow yexception() << "Parameter not found: " << name;
  298. }
  299. TExprNodeReplaceBuilder TExprNodeBuilder::Apply(ui32 index, const TExprNode& lambda) {
  300. Y_ENSURE(Container, "Container expected");
  301. Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
  302. "Container position mismatch, expected: " << Container->ChildrenSize() <<
  303. ", actual: " << index);
  304. return TExprNodeReplaceBuilder(this, Container, lambda.HeadPtr(), GetLambdaBody(lambda));
  305. }
  306. TExprNodeReplaceBuilder TExprNodeBuilder::Apply(const TExprNode& lambda) {
  307. Y_ENSURE(!Container || Container->Type() == TExprNode::Lambda, "No container expected");
  308. Y_ENSURE(!CurrentNode, "Node is already build");
  309. return TExprNodeReplaceBuilder(this, Container, lambda.HeadPtr(), GetLambdaBody(lambda));
  310. }
  311. TExprNodeReplaceBuilder TExprNodeBuilder::Apply(ui32 index, const TExprNode::TPtr& lambda) {
  312. return Apply(index, *lambda);
  313. }
  314. TExprNodeReplaceBuilder TExprNodeBuilder::Apply(const TExprNode::TPtr& lambda) {
  315. return Apply(*lambda);
  316. }
  317. TExprNodeReplaceBuilder TExprNodeBuilder::ApplyPartial(ui32 index, TExprNode::TPtr args, TExprNode::TPtr body) {
  318. Y_ENSURE(Container, "Container expected");
  319. Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
  320. "Container position mismatch, expected: " << Container->ChildrenSize() <<
  321. ", actual: " << index);
  322. Y_ENSURE(!args || args->IsArguments());
  323. return TExprNodeReplaceBuilder(this, Container, std::move(args), std::move(body));
  324. }
  325. TExprNodeReplaceBuilder TExprNodeBuilder::ApplyPartial(ui32 index, TExprNode::TPtr args, TExprNode::TListType body) {
  326. Y_ENSURE(Container, "Container expected");
  327. Y_ENSURE(Container->ChildrenSize() == index + (Container->IsLambda() ? 1U : 0U),
  328. "Container position mismatch, expected: " << Container->ChildrenSize() <<
  329. ", actual: " << index);
  330. Y_ENSURE(!args || args->IsArguments());
  331. return TExprNodeReplaceBuilder(this, Container, std::move(args), std::move(body));
  332. }
  333. TExprNodeReplaceBuilder TExprNodeBuilder::ApplyPartial(TExprNode::TPtr args, TExprNode::TPtr body) {
  334. Y_ENSURE(!Container || Container->Type() == TExprNode::Lambda, "No container expected");
  335. Y_ENSURE(!CurrentNode, "Node is already build");
  336. Y_ENSURE(!args || args->IsArguments());
  337. return TExprNodeReplaceBuilder(this, Container, std::move(args), std::move(body));
  338. }
  339. TExprNodeReplaceBuilder TExprNodeBuilder::ApplyPartial(TExprNode::TPtr args, TExprNode::TListType body) {
  340. Y_ENSURE(!Container || Container->Type() == TExprNode::Lambda, "No container expected");
  341. Y_ENSURE(!CurrentNode, "Node is already build");
  342. Y_ENSURE(!args || args->IsArguments());
  343. return TExprNodeReplaceBuilder(this, Container, std::move(args), std::move(body));
  344. }
  345. TExprNodeReplaceBuilder::TExprNodeReplaceBuilder(TExprNodeBuilder* owner, TExprNode::TPtr container,
  346. TExprNode::TPtr&& args, TExprNode::TPtr&& body)
  347. : Owner(owner)
  348. , Container(std::move(container))
  349. , Args(std::move(args))
  350. , Body({std::move(body)})
  351. , CurrentIndex(0)
  352. , CurrentNode(nullptr)
  353. {
  354. }
  355. TExprNodeReplaceBuilder::TExprNodeReplaceBuilder(TExprNodeBuilder* owner, TExprNode::TPtr container,
  356. TExprNode::TPtr&& args, TExprNode::TListType&& body)
  357. : Owner(owner)
  358. , Container(std::move(container))
  359. , Args(std::move(args))
  360. , Body(std::move(body))
  361. , CurrentIndex(0)
  362. , CurrentNode(nullptr)
  363. {
  364. }
  365. TExprNodeReplaceBuilder::TExprNodeReplaceBuilder(TExprNodeBuilder* owner, TExprNode::TPtr container,
  366. const TExprNode& lambda)
  367. : TExprNodeReplaceBuilder(owner, std::move(container), lambda.HeadPtr(), lambda.TailPtr())
  368. {
  369. Y_ENSURE(lambda.Type() == TExprNode::Lambda, "Expected lambda");
  370. }
  371. TExprNodeReplaceBuilder& TExprNodeReplaceBuilder::With(
  372. ui32 argIndex, const TStringBuf& toName) {
  373. Y_ENSURE(Args, "No arguments");
  374. Y_ENSURE(argIndex < Args->ChildrenSize(), "Wrong argument index");
  375. Body = Owner->Ctx.ReplaceNodes(std::move(Body), {{Args->Child(argIndex), Owner->FindArgument(toName)}});
  376. return *this;
  377. }
  378. TExprNodeReplaceBuilder& TExprNodeReplaceBuilder::With(
  379. ui32 argIndex, TExprNode::TPtr toNode) {
  380. Y_ENSURE(Args, "No arguments");
  381. Y_ENSURE(argIndex < Args->ChildrenSize(), "Wrong argument index");
  382. Body = Owner->Ctx.ReplaceNodes(std::move(Body), {{Args->Child(argIndex), std::move(toNode)}});
  383. return *this;
  384. }
  385. TExprNodeReplaceBuilder& TExprNodeReplaceBuilder::With(const TStringBuf& toName) {
  386. Y_ENSURE(Args, "No arguments");
  387. Y_ENSURE(!toName.empty(), "Empty parameter name is not allowed");
  388. TNodeOnNodeOwnedMap replaces(Args->ChildrenSize());
  389. for (ui32 i = 0U; i < Args->ChildrenSize(); ++i)
  390. Y_ENSURE(replaces.emplace(Args->Child(i), Owner->FindArgument(TString(toName) += ToString(i))).second, "Must be uinique.");
  391. Body = Owner->Ctx.ReplaceNodes(std::move(Body), replaces);
  392. return *this;
  393. }
  394. TExprNodeReplaceBuilder& TExprNodeReplaceBuilder::With(const TStringBuf& toName, ui32 toIndex) {
  395. Y_ENSURE(!toName.empty(), "Empty parameter name is not allowed");
  396. return With(TString(toName) += ToString(toIndex));
  397. }
  398. TExprNodeReplaceBuilder& TExprNodeReplaceBuilder::With(ui32 argIndex, const TStringBuf& toName, ui32 toIndex) {
  399. Y_ENSURE(!toName.empty(), "Empty parameter name is not allowed");
  400. return With(argIndex, TString(toName) += ToString(toIndex));
  401. }
  402. TExprNodeReplaceBuilder& TExprNodeReplaceBuilder::WithNode(const TExprNode& fromNode, TExprNode::TPtr&& toNode) {
  403. Body = Owner->Ctx.ReplaceNodes(std::move(Body), {{&fromNode, std::move(toNode)}});
  404. return *this;
  405. }
  406. TExprNodeReplaceBuilder& TExprNodeReplaceBuilder::WithNode(const TExprNode& fromNode, const TStringBuf& toName) {
  407. return WithNode(fromNode, Owner->FindArgument(toName));
  408. }
  409. TExprNodeBuilder TExprNodeReplaceBuilder::With(ui32 argIndex) {
  410. CurrentIndex = argIndex;
  411. return TExprNodeBuilder(Owner->Pos, this);
  412. }
  413. TExprNodeBuilder TExprNodeReplaceBuilder::WithNode(TExprNode::TPtr&& fromNode) {
  414. CurrentNode = std::move(fromNode);
  415. return TExprNodeBuilder(Owner->Pos, this);
  416. }
  417. TExprNodeBuilder& TExprNodeReplaceBuilder::Seal() {
  418. if (Container) {
  419. std::move(Body.begin(), Body.end(), std::back_inserter(Container->Children_));
  420. } else {
  421. Y_ENSURE(1U == Body.size() && Body.front(), "Expected single node.");
  422. Owner->CurrentNode = std::move(Body.front());
  423. }
  424. Body.clear();
  425. return *Owner;
  426. }
  427. } // namespace NYql