mkql_node_printer.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  1. #include "mkql_node_printer.h"
  2. #include "mkql_node_visitor.h"
  3. #include <util/stream/str.h>
  4. #include <yql/essentials/public/udf/udf_types.h>
  5. #include <yql/essentials/parser/pg_catalog/catalog.h>
  6. namespace NKikimr {
  7. namespace NMiniKQL {
  8. namespace {
  9. class TPrintVisitor : public INodeVisitor {
  10. friend class TIndentScope;
  11. public:
  12. struct TIndentScope {
  13. TIndentScope(TPrintVisitor* self)
  14. : Self(self)
  15. {
  16. ++Self->Indent;
  17. }
  18. ~TIndentScope() {
  19. --Self->Indent;
  20. }
  21. TPrintVisitor* Self;
  22. };
  23. TPrintVisitor(bool singleLine)
  24. : SingleLine(singleLine)
  25. , Indent(0)
  26. {}
  27. void Visit(TTypeType& node) override {
  28. Y_UNUSED(node);
  29. WriteIndentation();
  30. Out << "Type (Type)";
  31. WriteNewline();
  32. }
  33. void Visit(TVoidType& node) override {
  34. Y_UNUSED(node);
  35. WriteIndentation();
  36. Out << "Type (Void) ";
  37. WriteNewline();
  38. }
  39. void Visit(TNullType& node) override {
  40. Y_UNUSED(node);
  41. WriteIndentation();
  42. Out << "Type (Null) ";
  43. WriteNewline();
  44. }
  45. void Visit(TEmptyListType& node) override {
  46. Y_UNUSED(node);
  47. WriteIndentation();
  48. Out << "Type (EmptyList) ";
  49. WriteNewline();
  50. }
  51. void Visit(TEmptyDictType& node) override {
  52. Y_UNUSED(node);
  53. WriteIndentation();
  54. Out << "Type (EmptyDict) ";
  55. WriteNewline();
  56. }
  57. void Visit(TDataType& node) override {
  58. WriteIndentation();
  59. auto slot = NUdf::FindDataSlot(node.GetSchemeType());
  60. Out << "Type (Data), schemeType: ";
  61. if (slot) {
  62. Out << GetDataTypeInfo(*slot).Name;
  63. if (node.GetSchemeType() == NUdf::TDataType<NUdf::TDecimal>::Id) {
  64. const auto params = static_cast<TDataDecimalType&>(node).GetParams();
  65. Out << '(' << int(params.first) << ',' << int(params.second) << ')';
  66. }
  67. } else {
  68. Out << "<" << node.GetSchemeType() << ">";
  69. }
  70. Out << ", schemeTypeId: ";
  71. Out << node.GetSchemeType();
  72. WriteNewline();
  73. }
  74. void Visit(TPgType& node) override {
  75. WriteIndentation();
  76. Out << "Type (Pg), name: " << NYql::NPg::LookupType(node.GetTypeId()).Name;
  77. WriteNewline();
  78. }
  79. void Visit(TStructType& node) override {
  80. WriteIndentation();
  81. Out << "Type (Struct) with " << node.GetMembersCount() << " members {";
  82. WriteNewline();
  83. {
  84. TIndentScope scope(this);
  85. for (ui32 index = 0; index < node.GetMembersCount(); ++index) {
  86. WriteIndentation();
  87. Out << "Member [" << node.GetMemberName(index) << "] : {";
  88. WriteNewline();
  89. {
  90. TIndentScope scope2(this);
  91. node.GetMemberType(index)->Accept(*this);
  92. }
  93. WriteIndentation();
  94. Out << "}";
  95. WriteNewline();
  96. }
  97. }
  98. WriteIndentation();
  99. Out << "}";
  100. WriteNewline();
  101. }
  102. void Visit(TListType& node) override {
  103. WriteIndentation();
  104. Out << "Type (List) {";
  105. WriteNewline();
  106. {
  107. TIndentScope scope(this);
  108. WriteIndentation();
  109. Out << "List item type: {";
  110. WriteNewline();
  111. {
  112. TIndentScope scope2(this);
  113. node.GetItemType()->Accept(*this);
  114. }
  115. WriteIndentation();
  116. Out << "}";
  117. WriteNewline();
  118. }
  119. WriteIndentation();
  120. Out << "}";
  121. WriteNewline();
  122. }
  123. void Visit(TStreamType& node) override {
  124. WriteIndentation();
  125. Out << "Type (Stream) {";
  126. WriteNewline();
  127. {
  128. TIndentScope scope(this);
  129. WriteIndentation();
  130. Out << "Stream item type: {";
  131. WriteNewline();
  132. {
  133. TIndentScope scope2(this);
  134. node.GetItemType()->Accept(*this);
  135. }
  136. WriteIndentation();
  137. Out << "}";
  138. WriteNewline();
  139. }
  140. WriteIndentation();
  141. Out << "}";
  142. WriteNewline();
  143. }
  144. void Visit(TFlowType& node) override {
  145. WriteIndentation();
  146. Out << "Type (Flow) {";
  147. WriteNewline();
  148. {
  149. TIndentScope scope(this);
  150. WriteIndentation();
  151. Out << "Flow item type: {";
  152. WriteNewline();
  153. {
  154. TIndentScope scope2(this);
  155. node.GetItemType()->Accept(*this);
  156. }
  157. WriteIndentation();
  158. Out << "}";
  159. WriteNewline();
  160. }
  161. WriteIndentation();
  162. Out << "}";
  163. WriteNewline();
  164. }
  165. void Visit(TBlockType& node) override {
  166. WriteIndentation();
  167. Out << "Type (Block) {";
  168. WriteNewline();
  169. {
  170. TIndentScope scope(this);
  171. WriteIndentation();
  172. Out << "Block item type: {";
  173. WriteNewline();
  174. {
  175. TIndentScope scope2(this);
  176. node.GetItemType()->Accept(*this);
  177. }
  178. WriteIndentation();
  179. Out << "}";
  180. WriteNewline();
  181. WriteIndentation();
  182. Out << "Block shape: " << (node.GetShape() == TBlockType::EShape::Scalar ? "Scalar" : "Many");
  183. WriteNewline();
  184. }
  185. WriteIndentation();
  186. Out << "}";
  187. WriteNewline();
  188. }
  189. void Visit(TOptionalType& node) override {
  190. WriteIndentation();
  191. Out << "Type (Optional) {";
  192. WriteNewline();
  193. {
  194. TIndentScope scope(this);
  195. WriteIndentation();
  196. Out << "Optional item type: {";
  197. WriteNewline();
  198. {
  199. TIndentScope scope2(this);
  200. node.GetItemType()->Accept(*this);
  201. }
  202. WriteIndentation();
  203. Out << "}";
  204. WriteNewline();
  205. }
  206. WriteIndentation();
  207. Out << "}";
  208. WriteNewline();
  209. }
  210. void Visit(TDictType& node) override {
  211. WriteIndentation();
  212. Out << "Type (Dict) {";
  213. WriteNewline();
  214. {
  215. TIndentScope scope(this);
  216. WriteIndentation();
  217. Out << "Key type: {";
  218. WriteNewline();
  219. {
  220. TIndentScope scope2(this);
  221. node.GetKeyType()->Accept(*this);
  222. }
  223. WriteIndentation();
  224. Out << "}";
  225. WriteNewline();
  226. WriteIndentation();
  227. Out << "Payload type: {";
  228. WriteNewline();
  229. {
  230. TIndentScope scope2(this);
  231. node.GetPayloadType()->Accept(*this);
  232. }
  233. WriteIndentation();
  234. Out << "}";
  235. WriteNewline();
  236. }
  237. WriteIndentation();
  238. Out << "}";
  239. WriteNewline();
  240. }
  241. void Visit(TCallableType& node) override {
  242. WriteIndentation();
  243. Out << "Type (Callable), name: [" << node.GetName() << "] with " << node.GetArgumentsCount() << " args {";
  244. WriteNewline();
  245. {
  246. TIndentScope scope(this);
  247. WriteIndentation();
  248. Out << "Return type";
  249. if (node.IsMergeDisabled())
  250. Out << ", merge disabled";
  251. if (node.GetOptionalArgumentsCount() != 0)
  252. Out << ", optional args: " << node.GetOptionalArgumentsCount();
  253. Out << " : {";
  254. WriteNewline();
  255. {
  256. TIndentScope scope2(this);
  257. node.GetReturnType()->Accept(*this);
  258. }
  259. WriteIndentation();
  260. Out << "}";
  261. WriteNewline();
  262. for (ui32 index = 0; index < node.GetArgumentsCount(); ++index) {
  263. WriteIndentation();
  264. const auto& type = node.GetArgumentType(index);
  265. Out << "Argument #" << index << " : {";
  266. WriteNewline();
  267. {
  268. TIndentScope scope2(this);
  269. type->Accept(*this);
  270. }
  271. WriteIndentation();
  272. Out << "}";
  273. WriteNewline();
  274. }
  275. if (node.GetPayload()) {
  276. WriteIndentation();
  277. Out << "Payload: {";
  278. WriteNewline();
  279. {
  280. TIndentScope scope2(this);
  281. node.GetPayload()->Accept(*this);
  282. }
  283. WriteIndentation();
  284. Out << "}";
  285. WriteNewline();
  286. }
  287. }
  288. WriteIndentation();
  289. Out << "}";
  290. WriteNewline();
  291. }
  292. void Visit(TAnyType& node) override {
  293. Y_UNUSED(node);
  294. WriteIndentation();
  295. Out << "Type (Any) ";
  296. WriteNewline();
  297. }
  298. template<typename T>
  299. void VisitTupleLike(T& node, std::string_view name) {
  300. WriteIndentation();
  301. Out << "Type (" << name << ") with " << node.GetElementsCount() << " elements {";
  302. WriteNewline();
  303. {
  304. TIndentScope scope(this);
  305. for (ui32 index = 0; index < node.GetElementsCount(); ++index) {
  306. WriteIndentation();
  307. Out << "#" << index << " : {";
  308. WriteNewline();
  309. {
  310. TIndentScope scope2(this);
  311. node.GetElementType(index)->Accept(*this);
  312. }
  313. WriteIndentation();
  314. Out << "}";
  315. WriteNewline();
  316. }
  317. }
  318. WriteIndentation();
  319. Out << "}";
  320. WriteNewline();
  321. }
  322. void Visit(TTupleType& node) override {
  323. VisitTupleLike(node, "Tuple");
  324. }
  325. void Visit(TMultiType& node) override {
  326. VisitTupleLike(node, "Multi");
  327. }
  328. void Visit(TResourceType& node) override {
  329. Y_UNUSED(node);
  330. WriteIndentation();
  331. Out << "Type (Resource) (" << node.GetTag() << ")";
  332. WriteNewline();
  333. }
  334. void Visit(TVariantType& node) override {
  335. WriteIndentation();
  336. Out << "Type (Variant) {";
  337. WriteNewline();
  338. {
  339. TIndentScope scope(this);
  340. WriteIndentation();
  341. Out << "Underlying type: {";
  342. WriteNewline();
  343. {
  344. TIndentScope scope2(this);
  345. node.GetUnderlyingType()->Accept(*this);
  346. }
  347. WriteIndentation();
  348. Out << "}";
  349. WriteNewline();
  350. }
  351. WriteIndentation();
  352. Out << "}";
  353. WriteNewline();
  354. }
  355. void Visit(TVoid& node) override {
  356. WriteIndentation();
  357. Out << "Void {";
  358. WriteNewline();
  359. {
  360. TIndentScope scope(this);
  361. node.GetType()->Accept(*this);
  362. }
  363. WriteIndentation();
  364. Out << "}";
  365. WriteNewline();
  366. }
  367. void Visit(TNull& node) override {
  368. WriteIndentation();
  369. Out << "Null {";
  370. WriteNewline();
  371. {
  372. TIndentScope scope(this);
  373. node.GetType()->Accept(*this);
  374. }
  375. WriteIndentation();
  376. Out << "}";
  377. WriteNewline();
  378. }
  379. void Visit(TEmptyList& node) override {
  380. WriteIndentation();
  381. Out << "EmptyList {";
  382. WriteNewline();
  383. {
  384. TIndentScope scope(this);
  385. node.GetType()->Accept(*this);
  386. }
  387. WriteIndentation();
  388. Out << "}";
  389. WriteNewline();
  390. }
  391. void Visit(TEmptyDict& node) override {
  392. WriteIndentation();
  393. Out << "EmptyDict {";
  394. WriteNewline();
  395. {
  396. TIndentScope scope(this);
  397. node.GetType()->Accept(*this);
  398. }
  399. WriteIndentation();
  400. Out << "}";
  401. WriteNewline();
  402. }
  403. void Visit(TDataLiteral& node) override {
  404. WriteIndentation();
  405. Out << "Data {";
  406. WriteNewline();
  407. {
  408. TIndentScope scope(this);
  409. node.GetType()->Accept(*this);
  410. WriteIndentation();
  411. if (node.GetType()->GetSchemeType() == 0) {
  412. Out << "null";
  413. WriteNewline();
  414. } else {
  415. Out << TString(node.AsValue().AsStringRef()).Quote();
  416. WriteNewline();
  417. }
  418. }
  419. WriteIndentation();
  420. Out << "}";
  421. WriteNewline();
  422. }
  423. void Visit(TStructLiteral& node) override {
  424. WriteIndentation();
  425. Out << "Struct {";
  426. WriteNewline();
  427. {
  428. TIndentScope scope(this);
  429. for (ui32 index = 0; index < node.GetValuesCount(); ++index) {
  430. WriteIndentation();
  431. const auto& value = node.GetValue(index);
  432. Out << "Member [" << node.GetType()->GetMemberName(index) << "], "
  433. << (value.IsImmediate() ? "immediate" : "not immediate") << " {";
  434. WriteNewline();
  435. {
  436. TIndentScope scope2(this);
  437. value.GetNode()->Accept(*this);
  438. }
  439. WriteIndentation();
  440. Out << "}";
  441. WriteNewline();
  442. }
  443. }
  444. WriteIndentation();
  445. Out << "}";
  446. WriteNewline();
  447. }
  448. void Visit(TListLiteral& node) override {
  449. WriteIndentation();
  450. Out << "List with " << node.GetItemsCount() << " items {";
  451. WriteNewline();
  452. {
  453. TIndentScope scope(this);
  454. node.GetType()->Accept(*this);
  455. ui32 index = 0;
  456. for (ui32 i = 0; i < node.GetItemsCount(); ++i) {
  457. WriteIndentation();
  458. const auto& item = node.GetItems()[i];
  459. Out << "Item #" << index << ", " << (item.IsImmediate() ? "immediate" : "not immediate") << " {";
  460. WriteNewline();
  461. {
  462. TIndentScope scope2(this);
  463. item.GetNode()->Accept(*this);
  464. }
  465. WriteIndentation();
  466. Out << "}";
  467. WriteNewline();
  468. }
  469. }
  470. WriteIndentation();
  471. Out << "}";
  472. WriteNewline();
  473. }
  474. void Visit(TOptionalLiteral& node) override {
  475. WriteIndentation();
  476. Out << "Optional " << (node.HasItem() ? "with data" : "empty") << " {";
  477. WriteNewline();
  478. {
  479. TIndentScope scope(this);
  480. node.GetType()->Accept(*this);
  481. if (node.HasItem()) {
  482. WriteIndentation();
  483. const auto& item = node.GetItem();
  484. Out << "Item " << (item.IsImmediate() ? "immediate" : "not immediate") << " {";
  485. WriteNewline();
  486. {
  487. TIndentScope scope2(this);
  488. item.GetNode()->Accept(*this);
  489. }
  490. WriteIndentation();
  491. Out << "}";
  492. WriteNewline();
  493. }
  494. }
  495. WriteIndentation();
  496. Out << "}";
  497. WriteNewline();
  498. }
  499. void Visit(TDictLiteral& node) override {
  500. WriteIndentation();
  501. Out << "Dict with " << node.GetItemsCount() << " items {";
  502. WriteNewline();
  503. {
  504. TIndentScope scope(this);
  505. node.GetType()->Accept(*this);
  506. for (ui32 index = 0; index < node.GetItemsCount(); ++index) {
  507. WriteIndentation();
  508. const auto& item = node.GetItem(index);
  509. Out << "Key of item #" << index << ", " << (item.first.IsImmediate() ? "immediate" : "not immediate") << " {";
  510. WriteNewline();
  511. {
  512. TIndentScope scope2(this);
  513. item.first.GetNode()->Accept(*this);
  514. }
  515. WriteIndentation();
  516. Out << "}";
  517. WriteNewline();
  518. WriteIndentation();
  519. Out << "Payload of item #" << index << ", " << (item.second.IsImmediate() ? "immediate" : "not immediate") << " {";
  520. WriteNewline();
  521. {
  522. TIndentScope scope2(this);
  523. item.second.GetNode()->Accept(*this);
  524. }
  525. WriteIndentation();
  526. Out << "}";
  527. WriteNewline();
  528. }
  529. }
  530. WriteIndentation();
  531. Out << "}";
  532. WriteNewline();
  533. }
  534. void Visit(TCallable& node) override {
  535. WriteIndentation();
  536. Out << "Callable";
  537. if (node.GetUniqueId() != 0)
  538. Out << ", uniqueId: " << node.GetUniqueId();
  539. Out << " {";
  540. WriteNewline();
  541. {
  542. TIndentScope scope(this);
  543. node.GetType()->Accept(*this);
  544. for (ui32 index = 0; index < node.GetInputsCount(); ++index) {
  545. WriteIndentation();
  546. const auto& input = node.GetInput(index);
  547. Out << "Input #" << index << ", " << (input.IsImmediate() ? "immediate" : "not immediate") << " {";
  548. WriteNewline();
  549. {
  550. TIndentScope scope3(this);
  551. input.GetNode()->Accept(*this);
  552. }
  553. WriteIndentation();
  554. Out << "}";
  555. WriteNewline();
  556. }
  557. if (node.HasResult()) {
  558. WriteIndentation();
  559. Out << "Result, " << (node.GetResult().IsImmediate() ? "immediate" : "not immediate") << " {";
  560. WriteNewline();
  561. {
  562. TIndentScope scope3(this);
  563. node.GetResult().GetNode()->Accept(*this);
  564. }
  565. WriteIndentation();
  566. Out << "}";
  567. WriteNewline();
  568. }
  569. }
  570. WriteIndentation();
  571. Out << "}";
  572. WriteNewline();
  573. }
  574. void Visit(TAny& node) override {
  575. WriteIndentation();
  576. Out << "Any " << (node.HasItem() ? "with data" : "empty") << " {";
  577. WriteNewline();
  578. {
  579. TIndentScope scope(this);
  580. node.GetType()->Accept(*this);
  581. if (node.HasItem()) {
  582. WriteIndentation();
  583. const auto& item = node.GetItem();
  584. Out << "Item " << (item.IsImmediate() ? "immediate" : "not immediate") << " {";
  585. WriteNewline();
  586. {
  587. TIndentScope scope2(this);
  588. item.GetNode()->Accept(*this);
  589. }
  590. WriteIndentation();
  591. Out << "}";
  592. WriteNewline();
  593. }
  594. }
  595. WriteIndentation();
  596. Out << "}";
  597. WriteNewline();
  598. }
  599. void Visit(TTupleLiteral& node) override {
  600. WriteIndentation();
  601. Out << "Tuple {";
  602. WriteNewline();
  603. {
  604. TIndentScope scope(this);
  605. for (ui32 index = 0; index < node.GetValuesCount(); ++index) {
  606. WriteIndentation();
  607. const auto& value = node.GetValue(index);
  608. Out << "#" << index << " " << (value.IsImmediate() ? "immediate" : "not immediate") << " {";
  609. WriteNewline();
  610. {
  611. TIndentScope scope2(this);
  612. value.GetNode()->Accept(*this);
  613. }
  614. WriteIndentation();
  615. Out << "}";
  616. WriteNewline();
  617. }
  618. }
  619. WriteIndentation();
  620. Out << "}";
  621. WriteNewline();
  622. }
  623. void Visit(TVariantLiteral& node) override {
  624. WriteIndentation();
  625. Out << "Variant with alternative " << node.GetIndex() << " {";
  626. WriteNewline();
  627. {
  628. TIndentScope scope(this);
  629. node.GetType()->Accept(*this);
  630. WriteIndentation();
  631. const auto& item = node.GetItem();
  632. Out << "Item " << (item.IsImmediate() ? "immediate" : "not immediate") << " {";
  633. WriteNewline();
  634. {
  635. TIndentScope scope2(this);
  636. item.GetNode()->Accept(*this);
  637. }
  638. WriteIndentation();
  639. Out << "}";
  640. WriteNewline();
  641. }
  642. WriteIndentation();
  643. Out << "}";
  644. WriteNewline();
  645. }
  646. void Visit(TTaggedType& node) override {
  647. WriteIndentation();
  648. Out << "Type (Tagged) (" << node.GetTag() << ") {";
  649. WriteNewline();
  650. {
  651. TIndentScope scope(this);
  652. WriteIndentation();
  653. Out << "Tagged base type: {";
  654. WriteNewline();
  655. {
  656. TIndentScope scope2(this);
  657. node.GetBaseType()->Accept(*this);
  658. }
  659. WriteIndentation();
  660. Out << "}";
  661. WriteNewline();
  662. }
  663. WriteIndentation();
  664. Out << "}";
  665. WriteNewline();
  666. }
  667. TString ToString() {
  668. return Out.Str();
  669. }
  670. private:
  671. void WriteIndentation() {
  672. if (SingleLine) {
  673. } else {
  674. for (ui32 i = 0; i < 2 * Indent; ++i) {
  675. Out << ' ';
  676. }
  677. }
  678. }
  679. void WriteNewline() {
  680. if (SingleLine) {
  681. Out << ' ';
  682. } else {
  683. Out << '\n';
  684. }
  685. }
  686. private:
  687. const bool SingleLine;
  688. TStringStream Out;
  689. ui32 Indent;
  690. };
  691. }
  692. TString PrintNode(const TNode* node, bool singleLine) {
  693. TPrintVisitor visitor(singleLine);
  694. const_cast<TNode*>(node)->Accept(visitor);
  695. return visitor.ToString();
  696. }
  697. }
  698. }
  699. template <>
  700. void Out<NKikimr::NMiniKQL::TType>(
  701. IOutputStream& os,
  702. TTypeTraits<NKikimr::NMiniKQL::TType>::TFuncParam t
  703. )
  704. {
  705. os << PrintNode(&t, true);
  706. }