yql_expr_ut.cpp 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218
  1. #include "yql_expr.h"
  2. #include <library/cpp/testing/unittest/registar.h>
  3. #include <util/string/hex.h>
  4. namespace NYql {
  5. Y_UNIT_TEST_SUITE(TCompileYqlExpr) {
  6. static TAstParseResult ParseAstWithCheck(const TStringBuf& s) {
  7. TAstParseResult res = ParseAst(s);
  8. res.Issues.PrintTo(Cout);
  9. UNIT_ASSERT(res.IsOk());
  10. return res;
  11. }
  12. static void CompileExprWithCheck(TAstNode& root, TExprNode::TPtr& exprRoot, TExprContext& exprCtx, ui32 typeAnnotationIndex = Max<ui32>()) {
  13. const bool success = CompileExpr(root, exprRoot, exprCtx, nullptr, nullptr, typeAnnotationIndex != Max<ui32>(), typeAnnotationIndex);
  14. exprCtx.IssueManager.GetIssues().PrintTo(Cout);
  15. UNIT_ASSERT(success);
  16. UNIT_ASSERT_VALUES_EQUAL(exprRoot->GetState(), typeAnnotationIndex != Max<ui32>() ? TExprNode::EState::TypeComplete : TExprNode::EState::Initial);
  17. }
  18. static void CompileExprWithCheck(TAstNode& root, TLibraryCohesion& cohesion, TExprContext& exprCtx) {
  19. const bool success = CompileExpr(root, cohesion, exprCtx);
  20. exprCtx.IssueManager.GetIssues().PrintTo(Cout);
  21. UNIT_ASSERT(success);
  22. }
  23. static bool ParseAndCompile(const TString& program) {
  24. TAstParseResult astRes = ParseAstWithCheck(program);
  25. TExprContext exprCtx;
  26. TExprNode::TPtr exprRoot;
  27. bool result = CompileExpr(*astRes.Root, exprRoot, exprCtx, nullptr, nullptr);
  28. exprCtx.IssueManager.GetIssues().PrintTo(Cout);
  29. return result;
  30. }
  31. Y_UNIT_TEST(TestNoReturn1) {
  32. auto s = "(\n"
  33. ")\n";
  34. UNIT_ASSERT(false == ParseAndCompile(s));
  35. }
  36. Y_UNIT_TEST(TestNoReturn2) {
  37. auto s = "(\n"
  38. "(let x 'y)\n"
  39. ")\n";
  40. UNIT_ASSERT(false == ParseAndCompile(s));
  41. }
  42. Y_UNIT_TEST(TestExportInsteadOfReturn) {
  43. const auto s =
  44. "# library\n"
  45. "(\n"
  46. " (let sqr (lambda '(x) (* x x)))\n"
  47. " (export sqr)\n"
  48. ")\n"
  49. ;
  50. UNIT_ASSERT(false == ParseAndCompile(s));
  51. }
  52. Y_UNIT_TEST(TestLeftAfterReturn) {
  53. auto s = "(\n"
  54. "(return 'x)\n"
  55. "(let x 'y)\n"
  56. ")\n";
  57. UNIT_ASSERT(false == ParseAndCompile(s));
  58. }
  59. Y_UNIT_TEST(TestReturn) {
  60. auto s = "(\n"
  61. "(return world)\n"
  62. ")\n";
  63. TAstParseResult astRes = ParseAstWithCheck(s);
  64. TExprContext exprCtx;
  65. TExprNode::TPtr exprRoot;
  66. CompileExprWithCheck(*astRes.Root, exprRoot, exprCtx);
  67. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Type(), TExprNode::World);
  68. }
  69. Y_UNIT_TEST(TestExport) {
  70. auto s = "(\n"
  71. "(let X 'Y)\n"
  72. "(let ex '42)\n"
  73. "(export ex)\n"
  74. "(export X)\n"
  75. ")\n";
  76. TAstParseResult astRes = ParseAstWithCheck(s);
  77. TExprContext exprCtx;
  78. TLibraryCohesion cohesion;
  79. CompileExprWithCheck(*astRes.Root, cohesion, exprCtx);
  80. auto& exports = cohesion.Exports.Symbols(exprCtx);
  81. UNIT_ASSERT_VALUES_EQUAL(2U, exports.size());
  82. UNIT_ASSERT_VALUES_EQUAL("42", exports["ex"]->Content());
  83. UNIT_ASSERT_VALUES_EQUAL("Y", exports["X"]->Content());
  84. }
  85. Y_UNIT_TEST(TestEmptyLib) {
  86. auto s = "(\n"
  87. "(let X 'Y)\n"
  88. "(let ex '42)\n"
  89. ")\n";
  90. TAstParseResult astRes = ParseAstWithCheck(s);
  91. TExprContext exprCtx;
  92. TLibraryCohesion cohesion;
  93. CompileExprWithCheck(*astRes.Root, cohesion, exprCtx);
  94. UNIT_ASSERT(cohesion.Exports.Symbols().empty());
  95. UNIT_ASSERT(cohesion.Imports.empty());
  96. }
  97. Y_UNIT_TEST(TestArbitraryAtom) {
  98. auto s = "(\n"
  99. "(let x '\"\\x01\\x23\\x45\\x67\\x89\\xAB\\xCD\\xEF\")"
  100. "(return x)\n"
  101. ")\n";
  102. TAstParseResult astRes = ParseAstWithCheck(s);
  103. TExprContext exprCtx;
  104. TExprNode::TPtr exprRoot;
  105. CompileExprWithCheck(*astRes.Root, exprRoot, exprCtx);
  106. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Type(), TExprNode::Atom);
  107. UNIT_ASSERT_STRINGS_EQUAL(HexEncode(exprRoot->Content()), "0123456789ABCDEF");
  108. UNIT_ASSERT(exprRoot->Flags() & TNodeFlags::ArbitraryContent);
  109. auto ast = ConvertToAst(*exprRoot, exprCtx, TExprAnnotationFlags::None, true);
  110. TAstNode* xValue = ast.Root->GetChild(0)->GetChild(1)->GetChild(1);
  111. UNIT_ASSERT_STRINGS_EQUAL(HexEncode(TString(xValue->GetContent())), "0123456789ABCDEF");
  112. UNIT_ASSERT(xValue->GetFlags() & TNodeFlags::ArbitraryContent);
  113. }
  114. Y_UNIT_TEST(TestBinaryAtom) {
  115. auto s = "(\n"
  116. "(let x 'x\"FEDCBA9876543210\")"
  117. "(return x)\n"
  118. ")\n";
  119. TAstParseResult astRes = ParseAstWithCheck(s);
  120. TExprContext exprCtx;
  121. TExprNode::TPtr exprRoot;
  122. CompileExprWithCheck(*astRes.Root, exprRoot, exprCtx);
  123. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Type(), TExprNode::Atom);
  124. UNIT_ASSERT_STRINGS_EQUAL(HexEncode(exprRoot->Content()), "FEDCBA9876543210");
  125. UNIT_ASSERT(exprRoot->Flags() & TNodeFlags::BinaryContent);
  126. auto ast = ConvertToAst(*exprRoot, exprCtx, TExprAnnotationFlags::None, true);
  127. TAstNode* xValue = ast.Root->GetChild(0)->GetChild(2)->GetChild(1);
  128. UNIT_ASSERT_STRINGS_EQUAL(HexEncode(TString(xValue->GetContent())), "FEDCBA9876543210");
  129. UNIT_ASSERT(xValue->GetFlags() & TNodeFlags::BinaryContent);
  130. }
  131. Y_UNIT_TEST(TestLet) {
  132. auto s = "(\n"
  133. "(let x 'y)\n"
  134. "(return x)\n"
  135. ")\n";
  136. TAstParseResult astRes = ParseAstWithCheck(s);
  137. TExprContext exprCtx;
  138. TExprNode::TPtr exprRoot;
  139. CompileExprWithCheck(*astRes.Root, exprRoot, exprCtx);
  140. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Type(), TExprNode::Atom);
  141. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Content(), "y");
  142. }
  143. Y_UNIT_TEST(TestComplexQuote) {
  144. auto s = "(\n"
  145. "(let x 'a)\n"
  146. "(let y 'b)\n"
  147. "(let z (quote (x y)))\n"
  148. "(return z)\n"
  149. ")\n";
  150. TAstParseResult astRes = ParseAstWithCheck(s);
  151. TExprContext exprCtx;
  152. TExprNode::TPtr exprRoot;
  153. CompileExprWithCheck(*astRes.Root, exprRoot, exprCtx);
  154. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Type(), TExprNode::List);
  155. UNIT_ASSERT_VALUES_EQUAL(exprRoot->ChildrenSize(), 2);
  156. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(0)->Type(), TExprNode::Atom);
  157. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(0)->Content(), "a");
  158. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(1)->Type(), TExprNode::Atom);
  159. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(1)->Content(), "b");
  160. }
  161. Y_UNIT_TEST(TestEmptyReturn) {
  162. auto s = "(\n"
  163. "(return)\n"
  164. ")\n";
  165. UNIT_ASSERT(false == ParseAndCompile(s));
  166. }
  167. Y_UNIT_TEST(TestManyReturn) {
  168. auto s = "(\n"
  169. "(return world world)\n"
  170. ")\n";
  171. UNIT_ASSERT(false == ParseAndCompile(s));
  172. }
  173. Y_UNIT_TEST(TestUnknownFunction) {
  174. auto s = "(\n"
  175. "(let a '2)\n"
  176. "(let x (+ a '3))\n"
  177. "(return x)\n"
  178. ")\n";
  179. TAstParseResult astRes = ParseAstWithCheck(s);
  180. TExprContext exprCtx;
  181. TExprNode::TPtr exprRoot;
  182. CompileExprWithCheck(*astRes.Root, exprRoot, exprCtx);
  183. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Type(), TExprNode::Callable);
  184. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Content(), "+");
  185. UNIT_ASSERT_VALUES_EQUAL(exprRoot->ChildrenSize(), 2);
  186. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(0)->Type(), TExprNode::Atom);
  187. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(0)->Content(), "2");
  188. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(1)->Type(), TExprNode::Atom);
  189. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(1)->Content(), "3");
  190. }
  191. Y_UNIT_TEST(TestReturnTwice) {
  192. auto s = "(\n"
  193. "(return)\n"
  194. "(return)\n"
  195. ")\n";
  196. UNIT_ASSERT(false == ParseAndCompile(s));
  197. }
  198. Y_UNIT_TEST(TestDeclareNonTop) {
  199. const auto s = R"(
  200. (
  201. (let $1 (block '(
  202. (declare $param (DataType 'Uint32))
  203. (return $param)
  204. )))
  205. (return $1)
  206. )
  207. )";
  208. UNIT_ASSERT(false == ParseAndCompile(s));
  209. }
  210. Y_UNIT_TEST(TestDeclareHideLet) {
  211. const auto s = R"(
  212. (
  213. (let $name (Uint32 '10))
  214. (declare $name (DataType 'Uint32))
  215. (return $name)
  216. )
  217. )";
  218. UNIT_ASSERT(false == ParseAndCompile(s));
  219. }
  220. Y_UNIT_TEST(TestDeclareBadName) {
  221. const auto s = R"(
  222. (
  223. (declare $15 (DataType 'Uint32))
  224. (return $15)
  225. )
  226. )";
  227. UNIT_ASSERT(false == ParseAndCompile(s));
  228. }
  229. Y_UNIT_TEST(TestLetHideDeclare) {
  230. const auto s = R"(
  231. (
  232. (declare $name (DataType 'Uint32))
  233. (let $name (Uint32 '10))
  234. (return $name)
  235. )
  236. )";
  237. TAstParseResult astRes = ParseAstWithCheck(s);
  238. TExprContext exprCtx;
  239. TExprNode::TPtr exprRoot;
  240. CompileExprWithCheck(*astRes.Root, exprRoot, exprCtx);
  241. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Type(), TExprNode::Callable);
  242. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Content(), "Uint32");
  243. UNIT_ASSERT_VALUES_EQUAL(exprRoot->ChildrenSize(), 1);
  244. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(0)->Type(), TExprNode::Atom);
  245. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(0)->Content(), "10");
  246. }
  247. Y_UNIT_TEST(TestDeclare) {
  248. const auto s = R"(
  249. (
  250. (declare $param (DataType 'Uint32))
  251. (return $param)
  252. )
  253. )";
  254. TAstParseResult astRes = ParseAstWithCheck(s);
  255. TExprContext exprCtx;
  256. TExprNode::TPtr exprRoot;
  257. CompileExprWithCheck(*astRes.Root, exprRoot, exprCtx);
  258. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Type(), TExprNode::Callable);
  259. UNIT_ASSERT_VALUES_EQUAL(exprRoot->ChildrenSize(), 2);
  260. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(0)->Type(), TExprNode::Atom);
  261. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(0)->Content(), "$param");
  262. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(1)->Type(), TExprNode::Callable);
  263. UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(1)->Content(), "DataType");
  264. }
  265. }
  266. Y_UNIT_TEST_SUITE(TCompareExprTrees) {
  267. void CompileAndCompare(const TString& one, const TString& two, const std::pair<TPosition, TPosition> *const diffPositions = nullptr) {
  268. const auto progOne(ParseAst(one)), progTwo(ParseAst(two));
  269. UNIT_ASSERT(progOne.IsOk() && progTwo.IsOk());
  270. TExprContext ctxOne, ctxTwo;
  271. TExprNode::TPtr rootOne, rootTwo;
  272. UNIT_ASSERT(CompileExpr(*progOne.Root, rootOne, ctxOne, nullptr, nullptr));
  273. UNIT_ASSERT(CompileExpr(*progTwo.Root, rootTwo, ctxTwo, nullptr, nullptr));
  274. const TExprNode* diffOne = rootOne.Get();
  275. const TExprNode* diffTwo = rootTwo.Get();
  276. if (diffPositions) {
  277. UNIT_ASSERT(!CompareExprTrees(diffOne, diffTwo));
  278. UNIT_ASSERT_EQUAL(ctxOne.GetPosition(diffOne->Pos()), diffPositions->first);
  279. UNIT_ASSERT_EQUAL(ctxTwo.GetPosition(diffTwo->Pos()), diffPositions->second);
  280. } else
  281. UNIT_ASSERT(CompareExprTrees(diffOne, diffTwo));
  282. }
  283. Y_UNIT_TEST(BigGoodCompare) {
  284. const auto one = R"(
  285. (
  286. (let $1 world)
  287. (let $2 (DataSource '"yt" '"plato"))
  288. (let $3 (MrTableRange '"statbox/yql-log" '"2016-05-25" '"2016-06-01"))
  289. (let $4 '('table $3))
  290. (let $5 (Key $4))
  291. (let $6 '('"method" '"uri" '"login" '"user_agent" '"millis"))
  292. (let $7 '())
  293. (let $8 (Read! $1 $2 $5 $6 $7))
  294. (let $9 (Left! $8))
  295. (let $10 (DataSink 'result))
  296. (let $11 (Key))
  297. (let $12 (Right! $8))
  298. (let $13 (lambda '($111) (block '(
  299. (let $113 (Member $111 '"method"))
  300. (let $114 (String '"POST"))
  301. (let $115 (== $113 $114))
  302. (let $116 (Member $111 '"uri"))
  303. (let $117 (String '"/api/v2/operations"))
  304. (let $118 (== $116 $117))
  305. (let $119 (Udf '"String.HasPrefix"))
  306. (let $120 (Member $111 '"uri"))
  307. (let $121 (String '"/api/v2/tutorials/"))
  308. (let $122 (Apply $119 $120 $121))
  309. (let $123 (Or $118 $122))
  310. (let $124 (Udf '"String.HasPrefix"))
  311. (let $125 (Member $111 '"uri"))
  312. (let $126 (String '"/api/v2/queries/"))
  313. (let $127 (Apply $124 $125 $126))
  314. (let $128 (Or $123 $127))
  315. (let $129 (And $115 $128))
  316. (let $130 (Udf '"String.HasPrefix"))
  317. (let $131 (Member $111 '"uri"))
  318. (let $132 (String '"/api/v2/table_data_async"))
  319. (let $133 (Apply $130 $131 $132))
  320. (let $134 (Or $129 $133))
  321. (let $135 (Udf '"String.HasPrefix"))
  322. (let $136 (Member $111 '"login"))
  323. (let $137 (String '"robot-"))
  324. (let $138 (Apply $135 $136 $137))
  325. (let $139 (Not $138))
  326. (let $140 (And $134 $139))
  327. (let $141 (Bool 'false))
  328. (let $142 (Coalesce $140 $141))
  329. (return $142)
  330. ))))
  331. (let $14 (Filter $12 $13))
  332. (let $15 (lambda '($143) (block '(
  333. (let $145 (Struct))
  334. (let $146 (Member $143 '"login"))
  335. (let $147 (AddMember $145 '"login" $146))
  336. (let $148 (Udf '"String.HasPrefix"))
  337. (let $149 (Member $143 '"user_agent"))
  338. (let $150 (String '"YQL "))
  339. (let $151 (Apply $148 $149 $150))
  340. (let $152 (Bool 'false))
  341. (let $153 (Coalesce $151 $152))
  342. (let $154 (Udf '"String.SplitToList"))
  343. (let $155 (Member $143 '"user_agent"))
  344. (let $156 (String '" "))
  345. (let $157 (Apply $154 $155 $156))
  346. (let $158 (Int64 '"1"))
  347. (let $159 (SqlAccess 'dict $157 $158))
  348. (let $160 (String '"CLI"))
  349. (let $161 (== $159 $160))
  350. (let $162 (Bool 'false))
  351. (let $163 (Coalesce $161 $162))
  352. (let $164 (String '"CLI"))
  353. (let $165 (String '"API"))
  354. (let $166 (If $163 $164 $165))
  355. (let $167 (String '"Web UI"))
  356. (let $168 (If $153 $166 $167))
  357. (let $169 (AddMember $147 '"client_type" $168))
  358. (let $170 (Udf '"DateTime.ToDate"))
  359. (let $171 (Udf '"DateTime.StartOfWeek"))
  360. (let $172 (Udf '"DateTime.FromMilliSeconds"))
  361. (let $173 (Member $143 '"millis"))
  362. (let $174 (Cast $173 'Uint64))
  363. (let $175 (Apply $172 $174))
  364. (let $176 (Apply $171 $175))
  365. (let $177 (Apply $170 $176))
  366. (let $178 (String '""))
  367. (let $179 (Coalesce $177 $178))
  368. (let $180 (String '" - "))
  369. (let $181 (Concat $179 $180))
  370. (let $182 (Udf '"DateTime.ToDate"))
  371. (let $183 (Udf '"DateTime.StartOfWeek"))
  372. (let $184 (Udf '"DateTime.FromMilliSeconds"))
  373. (let $185 (Member $143 '"millis"))
  374. (let $186 (Cast $185 'Uint64))
  375. (let $187 (Apply $184 $186))
  376. (let $188 (Apply $183 $187))
  377. (let $189 (Udf '"DateTime.FromDays"))
  378. (let $190 (Int64 '"6"))
  379. (let $191 (Apply $189 $190))
  380. (let $192 (+ $188 $191))
  381. (let $193 (Apply $182 $192))
  382. (let $194 (String '""))
  383. (let $195 (Coalesce $193 $194))
  384. (let $196 (Concat $181 $195))
  385. (let $197 (AddMember $169 '"week" $196))
  386. (let $198 (AsList $197))
  387. (return $198)
  388. ))))
  389. )"
  390. R"(
  391. (let $16 (FlatMap $14 $15))
  392. (let $17 '('"client_type" '"week"))
  393. (let $18 (lambda '($199 $200) (block '(
  394. (let $202 (lambda '($205 $206 $207) (block '(
  395. (let $209 (ListItemType $205))
  396. (let $210 (lambda '($223) (block '(
  397. (let $212 (ListItemType $205))
  398. (let $213 (InstanceOf $212))
  399. (let $214 (Apply $206 $213))
  400. (let $215 (TypeOf $214))
  401. (let $216 (ListType $215))
  402. (let $217 (Apply $207 $216))
  403. (let $225 (NthArg '1 $217))
  404. (let $226 (Apply $206 $223))
  405. (let $227 (Apply $225 $226))
  406. (return $227)
  407. ))))
  408. (let $211 (lambda '($228 $229) (block '(
  409. (let $212 (ListItemType $205))
  410. (let $213 (InstanceOf $212))
  411. (let $214 (Apply $206 $213))
  412. (let $215 (TypeOf $214))
  413. (let $216 (ListType $215))
  414. (let $217 (Apply $207 $216))
  415. (let $231 (NthArg '2 $217))
  416. (let $232 (Apply $206 $228))
  417. (let $233 (Apply $231 $232 $229))
  418. (return $233)
  419. ))))
  420. (let $212 (ListItemType $205))
  421. (let $213 (InstanceOf $212))
  422. (let $214 (Apply $206 $213))
  423. (let $215 (TypeOf $214))
  424. (let $216 (ListType $215))
  425. (let $217 (Apply $207 $216))
  426. (let $218 (NthArg '3 $217))
  427. (let $219 (NthArg '4 $217))
  428. (let $220 (NthArg '5 $217))
  429. (let $221 (NthArg '6 $217))
  430. (let $222 (AggregationTraits $209 $210 $211 $218 $219 $220 $221))
  431. (return $222)
  432. ))))
  433. (let $203 (lambda '($234) (block '(
  434. (let $236 (ListItemType $234))
  435. (let $237 (lambda '($244) (block '(
  436. (let $246 (AggrCountInit $244))
  437. (return $246)
  438. ))))
  439. (let $238 (lambda '($247 $248) (block '(
  440. (let $250 (AggrCountUpdate $247 $248))
  441. (return $250)
  442. ))))
  443. (let $239 (lambda '($251) (block '(
  444. (return $251)
  445. ))))
  446. (let $240 (lambda '($253) (block '(
  447. (return $253)
  448. ))))
  449. (let $241 (lambda '($255 $256) (block '(
  450. (let $258 (+ $255 $256))
  451. (return $258)
  452. ))))
  453. (let $242 (lambda '($259) (block '(
  454. (return $259)
  455. ))))
  456. (let $243 (AggregationTraits $236 $237 $238 $239 $240 $241 $242))
  457. (return $243)
  458. ))))
  459. (let $204 (Apply $202 $199 $200 $203))
  460. (return $204)
  461. ))))
  462. (let $19 (TypeOf $16))
  463. (let $20 (ListItemType $19))
  464. (let $21 (StructMemberType $20 '"login"))
  465. (let $22 (ListType $21))
  466. (let $23 (lambda '($261) (block '(
  467. (return $261)
  468. ))))
  469. (let $24 (Apply $18 $22 $23))
  470. (let $25 '('Count1 $24 '"login"))
  471. (let $26 (TypeOf $16))
  472. (let $27 (lambda '($263) (block '(
  473. (let $265 (Void))
  474. (return $265)
  475. ))))
  476. (let $28 (Apply $18 $26 $27))
  477. (let $29 '('Count2 $28))
  478. (let $30 (TypeOf $16))
  479. (let $31 (lambda '($266) (block '(
  480. (let $268 (Void))
  481. (return $268)
  482. ))))
  483. (let $32 (Apply $18 $30 $31))
  484. (let $33 '('Count3 $32))
  485. (let $34 (TypeOf $16))
  486. (let $35 (ListItemType $34))
  487. (let $36 (StructMemberType $35 '"login"))
  488. (let $37 (ListType $36))
  489. (let $38 (lambda '($269) (block '(
  490. (return $269)
  491. ))))
  492. (let $39 (Apply $18 $37 $38))
  493. (let $40 '('Count4 $39 '"login"))
  494. (let $41 '($25 $29 $33 $40))
  495. (let $42 (Aggregate $16 $17 $41))
  496. (let $43 (lambda '($271) (block '(
  497. (let $273 (Struct))
  498. (let $274 (Member $271 '"week"))
  499. (let $275 (AddMember $273 '"week" $274))
  500. (let $276 (Member $271 '"client_type"))
  501. (let $277 (AddMember $275 '"client_type" $276))
  502. (let $278 (Member $271 'Count1))
  503. (let $279 (AddMember $277 '"users_count" $278))
  504. (let $280 (Member $271 'Count2))
  505. (let $281 (AddMember $279 '"operations_count" $280))
  506. (let $282 (Member $271 'Count3))
  507. (let $283 (Member $271 'Count4))
  508. (let $284 (/ $282 $283))
  509. (let $285 (AddMember $281 '"operations_per_user" $284))
  510. (let $286 (AsList $285))
  511. (return $286)
  512. ))))
  513. (let $44 (FlatMap $42 $43))
  514. (let $45 (Bool 'false))
  515. (let $46 (Bool 'false))
  516. (let $47 '($45 $46))
  517. (let $48 (lambda '($287) (block '(
  518. (let $289 (Member $287 '"week"))
  519. (let $290 (Member $287 '"users_count"))
  520. (let $291 '($289 $290))
  521. (return $291)
  522. ))))
  523. (let $49 (Sort $44 $47 $48))
  524. (let $50 '('type))
  525. (let $51 '('autoref))
  526. (let $52 '('"week" '"client_type" '"users_count" '"operations_count" '"operations_per_user"))
  527. (let $53 '('columns $52))
  528. (let $54 '($50 $51 $53))
  529. (let $55 (Write! $9 $10 $11 $49 $54))
  530. (let $56 (Commit! $55 $10))
  531. (let $57 (DataSource '"yt" '"plato"))
  532. (let $58 (MrTableRange '"statbox/yql-log" '"2016-05-25" '"2016-06-01"))
  533. (let $59 '('table $58))
  534. (let $60 (Key $59))
  535. (let $61 '('"method" '"uri" '"login" '"user_agent" '"millis"))
  536. (let $62 '())
  537. (let $63 (Read! $56 $57 $60 $61 $62))
  538. (let $64 (Left! $63))
  539. (let $65 (DataSink 'result))
  540. (let $66 (Key))
  541. (let $67 (Right! $63))
  542. (let $68 (lambda '($292) (block '(
  543. (let $294 (Member $292 '"method"))
  544. (let $295 (String '"POST"))
  545. (let $296 (== $294 $295))
  546. (let $297 (Member $292 '"uri"))
  547. (let $298 (String '"/api/v2/operations"))
  548. (let $299 (== $297 $298))
  549. (let $300 (Udf '"String.HasPrefix"))
  550. (let $301 (Member $292 '"uri"))
  551. (let $302 (String '"/api/v2/tutorials/"))
  552. (let $303 (Apply $300 $301 $302))
  553. (let $304 (Or $299 $303))
  554. (let $305 (Udf '"String.HasPrefix"))
  555. (let $306 (Member $292 '"uri"))
  556. (let $307 (String '"/api/v2/queries/"))
  557. (let $308 (Apply $305 $306 $307))
  558. (let $309 (Or $304 $308))
  559. (let $310 (And $296 $309))
  560. (let $311 (Udf '"String.HasPrefix"))
  561. (let $312 (Member $292 '"uri"))
  562. (let $313 (String '"/api/v2/table_data_async"))
  563. (let $314 (Apply $311 $312 $313))
  564. (let $315 (Or $310 $314))
  565. (let $316 (Udf '"String.HasPrefix"))
  566. (let $317 (Member $292 '"login"))
  567. (let $318 (String '"robot-"))
  568. (let $319 (Apply $316 $317 $318))
  569. (let $320 (Not $319))
  570. (let $321 (And $315 $320))
  571. (let $322 (Bool 'false))
  572. (let $323 (Coalesce $321 $322))
  573. (return $323)
  574. ))))
  575. (let $69 (Filter $67 $68))
  576. (let $70 (lambda '($324) (block '(
  577. (let $326 (Struct))
  578. (let $327 (Member $324 '"login"))
  579. (let $328 (AddMember $326 '"login" $327))
  580. (let $329 (Udf '"String.HasPrefix"))
  581. (let $330 (Member $324 '"user_agent"))
  582. (let $331 (String '"YQL "))
  583. (let $332 (Apply $329 $330 $331))
  584. (let $333 (Bool 'false))
  585. (let $334 (Coalesce $332 $333))
  586. (let $335 (Udf '"String.SplitToList"))
  587. (let $336 (Member $324 '"user_agent"))
  588. (let $337 (String '" "))
  589. (let $338 (Apply $335 $336 $337))
  590. (let $339 (Int64 '"1"))
  591. (let $340 (SqlAccess 'dict $338 $339))
  592. (let $341 (String '"CLI"))
  593. (let $342 (== $340 $341))
  594. (let $343 (Bool 'false))
  595. (let $344 (Coalesce $342 $343))
  596. (let $345 (String '"CLI"))
  597. (let $346 (String '"API"))
  598. (let $347 (If $344 $345 $346))
  599. (let $348 (String '"Web UI"))
  600. (let $349 (If $334 $347 $348))
  601. (let $350 (AddMember $328 '"client_type" $349))
  602. (let $351 (Udf '"DateTime.ToDate"))
  603. (let $352 (Udf '"DateTime.StartOfWeek"))
  604. (let $353 (Udf '"DateTime.FromMilliSeconds"))
  605. (let $354 (Member $324 '"millis"))
  606. (let $355 (Cast $354 'Uint64))
  607. (let $356 (Apply $353 $355))
  608. (let $357 (Apply $352 $356))
  609. (let $358 (Apply $351 $357))
  610. (let $359 (String '""))
  611. (let $360 (Coalesce $358 $359))
  612. (let $361 (String '" - "))
  613. (let $362 (Concat $360 $361))
  614. (let $363 (Udf '"DateTime.ToDate"))
  615. (let $364 (Udf '"DateTime.StartOfWeek"))
  616. (let $365 (Udf '"DateTime.FromMilliSeconds"))
  617. (let $366 (Member $324 '"millis"))
  618. (let $367 (Cast $366 'Uint64))
  619. (let $368 (Apply $365 $367))
  620. (let $369 (Apply $364 $368))
  621. (let $370 (Udf '"DateTime.FromDays"))
  622. (let $371 (Int64 '"6"))
  623. (let $372 (Apply $370 $371))
  624. (let $373 (+ $369 $372))
  625. (let $374 (Apply $363 $373))
  626. (let $375 (String '""))
  627. (let $376 (Coalesce $374 $375))
  628. (let $377 (Concat $362 $376))
  629. (let $378 (AddMember $350 '"week" $377))
  630. (let $379 (AsList $378))
  631. (return $379)
  632. ))))
  633. (let $71 (FlatMap $69 $70))
  634. (let $72 '('"week"))
  635. (let $73 (TypeOf $71))
  636. (let $74 (ListItemType $73))
  637. (let $75 (StructMemberType $74 '"login"))
  638. (let $76 (ListType $75))
  639. (let $77 (lambda '($380) (block '(
  640. (return $380)
  641. ))))
  642. (let $78 (Apply $18 $76 $77))
  643. (let $79 '('Count6 $78 '"login"))
  644. (let $80 (TypeOf $71))
  645. (let $81 (lambda '($382) (block '(
  646. (let $384 (Void))
  647. (return $384)
  648. ))))
  649. (let $82 (Apply $18 $80 $81))
  650. (let $83 '('Count7 $82))
  651. (let $84 (TypeOf $71))
  652. (let $85 (lambda '($385) (block '(
  653. (let $387 (Void))
  654. (return $387)
  655. ))))
  656. (let $86 (Apply $18 $84 $85))
  657. (let $87 '('Count8 $86))
  658. (let $88 (TypeOf $71))
  659. (let $89 (ListItemType $88))
  660. (let $90 (StructMemberType $89 '"login"))
  661. (let $91 (ListType $90))
  662. (let $92 (lambda '($388) (block '(
  663. (return $388)
  664. ))))
  665. (let $93 (Apply $18 $91 $92))
  666. (let $94 '('Count9 $93 '"login"))
  667. (let $95 '($79 $83 $87 $94))
  668. (let $96 (Aggregate $71 $72 $95))
  669. (let $97 (lambda '($390) (block '(
  670. (let $392 (Struct))
  671. (let $393 (Member $390 '"week"))
  672. (let $394 (AddMember $392 '"week" $393))
  673. (let $395 (Member $390 'Count6))
  674. (let $396 (AddMember $394 '"users_count" $395))
  675. (let $397 (Member $390 'Count7))
  676. (let $398 (AddMember $396 '"operations_count" $397))
  677. (let $399 (Member $390 'Count8))
  678. (let $400 (Member $390 'Count9))
  679. (let $401 (/ $399 $400))
  680. (let $402 (AddMember $398 '"operations_per_user" $401))
  681. (let $403 (AsList $402))
  682. (return $403)
  683. ))))
  684. (let $98 (FlatMap $96 $97))
  685. (let $99 (Bool 'false))
  686. (let $100 (lambda '($404) (block '(
  687. (let $406 (Member $404 '"week"))
  688. (return $406)
  689. ))))
  690. (let $101 (Sort $98 $99 $100))
  691. (let $102 '('type))
  692. (let $103 '('autoref))
  693. (let $104 '('"week" '"users_count" '"operations_count" '"operations_per_user"))
  694. (let $105 '('columns $104))
  695. (let $106 '($102 $103 $105))
  696. (let $107 (Write! $64 $65 $66 $101 $106))
  697. (let $108 (Commit! $107 $65))
  698. (let $109 (DataSink '"yt" '"plato"))
  699. (let $110 (Commit! $108 $109))
  700. (return $110)
  701. )
  702. )";
  703. const auto two = R"(
  704. (
  705. (let $1 (MrTableRange '"statbox/yql-log" '"2016-05-25" '"2016-06-01"))
  706. (let $2 '('"method" '"uri" '"login" '"user_agent" '"millis"))
  707. (let $3 (Read! world (DataSource '"yt" '"plato") (Key '('table $1)) $2 '()))
  708. (let $4 (DataSink 'result))
  709. (let $5 (FlatMap (Filter (Right! $3) (lambda '($36) (block '(
  710. (let $37 (Apply (Udf '"String.HasPrefix") (Member $36 '"uri") (String '"/api/v2/tutorials/")))
  711. (let $38 (Apply (Udf '"String.HasPrefix") (Member $36 '"uri") (String '"/api/v2/queries/")))
  712. (let $39 (Apply (Udf '"String.HasPrefix") (Member $36 '"uri") (String '"/api/v2/table_data_async")))
  713. (let $40 (Apply (Udf '"String.HasPrefix") (Member $36 '"login") (String '"robot-")))
  714. (return (Coalesce (And (Or (And (== (Member $36 '"method") (String '"POST")) (Or (Or (== (Member $36 '"uri") (String '"/api/v2/operations")) $37) $38)) $39) (Not $40)) (Bool 'false)))
  715. )))) (lambda '($41) (block '(
  716. (let $42 (AddMember (Struct) '"login" (Member $41 '"login")))
  717. (let $43 (Apply (Udf '"String.HasPrefix") (Member $41 '"user_agent") (String '"YQL ")))
  718. (let $44 (Apply (Udf '"String.SplitToList") (Member $41 '"user_agent") (String '" ")))
  719. (let $45 (SqlAccess 'dict $44 (Int64 '"1")))
  720. (let $46 (If (Coalesce (== $45 (String '"CLI")) (Bool 'false)) (String '"CLI") (String '"API")))
  721. (let $47 (If (Coalesce $43 (Bool 'false)) $46 (String '"Web UI")))
  722. (let $48 (AddMember $42 '"client_type" $47))
  723. (let $49 (AddMember $48 '"week" (Concat (Concat (Coalesce (Apply (Udf '"DateTime.ToDate") (Apply (Udf '"DateTime.StartOfWeek") (Apply (Udf '"DateTime.FromMilliSeconds") (Cast (Member $41 '"millis") 'Uint64)))) (String '"")) (String '" - ")) (Coalesce (Apply (Udf '"DateTime.ToDate") (+ (Apply (Udf '"DateTime.StartOfWeek") (Apply (Udf '"DateTime.FromMilliSeconds") (Cast (Member $41 '"millis") 'Uint64))) (Apply (Udf '"DateTime.FromDays") (Int64 '"6")))) (String '"")))))
  724. (return (AsList $49))
  725. )))))
  726. (let $6 (lambda '($50 $51) (block '(
  727. (let $52 (Apply (lambda '($53 $54 $55) (block '(
  728. (let $57 (Apply $55 (ListType (TypeOf (Apply $54 (InstanceOf (ListItemType $53)))))))
  729. (let $58 (AggregationTraits (ListItemType $53) (lambda '($59) (block '(
  730. (let $57 (Apply $55 (ListType (TypeOf (Apply $54 (InstanceOf (ListItemType $53)))))))
  731. (return (Apply (NthArg '1 $57) (Apply $54 $59)))
  732. ))) (lambda '($60 $61) (block '(
  733. (let $57 (Apply $55 (ListType (TypeOf (Apply $54 (InstanceOf (ListItemType $53)))))))
  734. (let $62 (Apply (NthArg '2 $57) (Apply $54 $60) $61))
  735. (return $62)
  736. ))) (NthArg '3 $57) (NthArg '4 $57) (NthArg '5 $57) (NthArg '6 $57)))
  737. (return $58)
  738. ))) $50 $51 (lambda '($63) (block '(
  739. (let $64 (AggregationTraits (ListItemType $63) (lambda '($65) (AggrCountInit $65)) (lambda '($66 $67) (AggrCountUpdate $66 $67)) (lambda '($68) $68) (lambda '($69) $69) (lambda '($70 $71) (+ $70 $71)) (lambda '($72) $72)))
  740. (return $64)
  741. )))))
  742. (return $52)
  743. ))))
  744. (let $7 (Apply $6 (ListType (StructMemberType (ListItemType (TypeOf $5)) '"login")) (lambda '($73) $73)))
  745. (let $8 '('Count1 $7 '"login"))
  746. (let $9 (Apply $6 (TypeOf $5) (lambda '($74) (Void))))
  747. (let $10 (Apply $6 (TypeOf $5) (lambda '($75) (Void))))
  748. (let $11 (Apply $6 (ListType (StructMemberType (ListItemType (TypeOf $5)) '"login")) (lambda '($76) $76)))
  749. (let $12 '('Count4 $11 '"login"))
  750. (let $13 '($8 '('Count2 $9) '('Count3 $10) $12))
  751. (let $14 (Aggregate $5 '('"client_type" '"week") $13))
  752. (let $15 (Sort (FlatMap $14 (lambda '($77) (block '(
  753. (let $78 (AddMember (Struct) '"week" (Member $77 '"week")))
  754. (let $79 (AddMember $78 '"client_type" (Member $77 '"client_type")))
  755. (let $80 (AddMember $79 '"users_count" (Member $77 'Count1)))
  756. (let $81 (AddMember $80 '"operations_count" (Member $77 'Count2)))
  757. (let $82 (AddMember $81 '"operations_per_user" (/ (Member $77 'Count3) (Member $77 'Count4))))
  758. (return (AsList $82))
  759. )))) '((Bool 'false) (Bool 'false)) (lambda '($83) '((Member $83 '"week") (Member $83 '"users_count")))))
  760. (let $16 '('"week" '"client_type" '"users_count" '"operations_count" '"operations_per_user"))
  761. (let $17 '('('type) '('autoref) '('columns $16)))
  762. (let $18 (Write! (Left! $3) $4 (Key) $15 $17))
  763. (let $19 (MrTableRange '"statbox/yql-log" '"2016-05-25" '"2016-06-01"))
  764. (let $20 '('"method" '"uri" '"login" '"user_agent" '"millis"))
  765. (let $21 (Read! (Commit! $18 $4) (DataSource '"yt" '"plato") (Key '('table $19)) $20 '()))
  766. (let $22 (DataSink 'result))
  767. (let $23 (FlatMap (Filter (Right! $21) (lambda '($84) (block '(
  768. (let $85 (Apply (Udf '"String.HasPrefix") (Member $84 '"uri") (String '"/api/v2/tutorials/")))
  769. (let $86 (Apply (Udf '"String.HasPrefix") (Member $84 '"uri") (String '"/api/v2/queries/")))
  770. (let $87 (Apply (Udf '"String.HasPrefix") (Member $84 '"uri") (String '"/api/v2/table_data_async")))
  771. (let $88 (Apply (Udf '"String.HasPrefix") (Member $84 '"login") (String '"robot-")))
  772. (return (Coalesce (And (Or (And (== (Member $84 '"method") (String '"POST")) (Or (Or (== (Member $84 '"uri") (String '"/api/v2/operations")) $85) $86)) $87) (Not $88)) (Bool 'false)))
  773. )))) (lambda '($89) (block '(
  774. (let $90 (AddMember (Struct) '"login" (Member $89 '"login")))
  775. (let $91 (Apply (Udf '"String.HasPrefix") (Member $89 '"user_agent") (String '"YQL ")))
  776. (let $92 (Apply (Udf '"String.SplitToList") (Member $89 '"user_agent") (String '" ")))
  777. (let $93 (SqlAccess 'dict $92 (Int64 '"1")))
  778. (let $94 (If (Coalesce (== $93 (String '"CLI")) (Bool 'false)) (String '"CLI") (String '"API")))
  779. (let $95 (If (Coalesce $91 (Bool 'false)) $94 (String '"Web UI")))
  780. (let $96 (AddMember $90 '"client_type" $95))
  781. (let $97 (AddMember $96 '"week" (Concat (Concat (Coalesce (Apply (Udf '"DateTime.ToDate") (Apply (Udf '"DateTime.StartOfWeek") (Apply (Udf '"DateTime.FromMilliSeconds") (Cast (Member $89 '"millis") 'Uint64)))) (String '"")) (String '" - ")) (Coalesce (Apply (Udf '"DateTime.ToDate") (+ (Apply (Udf '"DateTime.StartOfWeek") (Apply (Udf '"DateTime.FromMilliSeconds") (Cast (Member $89 '"millis") 'Uint64))) (Apply (Udf '"DateTime.FromDays") (Int64 '"6")))) (String '"")))))
  782. (return (AsList $97))
  783. )))))
  784. (let $24 (Apply $6 (ListType (StructMemberType (ListItemType (TypeOf $23)) '"login")) (lambda '($98) $98)))
  785. (let $25 '('Count6 $24 '"login"))
  786. (let $26 (Apply $6 (TypeOf $23) (lambda '($99) (Void))))
  787. (let $27 (Apply $6 (TypeOf $23) (lambda '($100) (Void))))
  788. (let $28 (Apply $6 (ListType (StructMemberType (ListItemType (TypeOf $23)) '"login")) (lambda '($101) $101)))
  789. (let $29 '('Count9 $28 '"login"))
  790. (let $30 '($25 '('Count7 $26) '('Count8 $27) $29))
  791. (let $31 (Aggregate $23 '('"week") $30))
  792. (let $32 (Sort (FlatMap $31 (lambda '($102) (block '(
  793. (let $103 (AddMember (Struct) '"week" (Member $102 '"week")))
  794. (let $104 (AddMember $103 '"users_count" (Member $102 'Count6)))
  795. (let $105 (AddMember $104 '"operations_count" (Member $102 'Count7)))
  796. (let $106 (AddMember $105 '"operations_per_user" (/ (Member $102 'Count8) (Member $102 'Count9))))
  797. (return (AsList $106))
  798. )))) (Bool 'false) (lambda '($107) (Member $107 '"week"))))
  799. (let $33 '('"week" '"users_count" '"operations_count" '"operations_per_user"))
  800. (let $34 '('('type) '('autoref) '('columns $33)))
  801. (let $35 (Write! (Left! $21) $22 (Key) $32 $34))
  802. (return (Commit! (Commit! $35 $22) (DataSink '"yt" '"plato")))
  803. )
  804. )";
  805. CompileAndCompare(one, two);
  806. }
  807. Y_UNIT_TEST(DiffrentAtoms) {
  808. const auto one = "((return (+ '4 (- '3 '2))))";
  809. const auto two = "((let x '3)\n(let y '1)\n(let z (- x y))\n(let r (+ '4 z))\n(return r))";
  810. const auto diff = std::make_pair(TPosition(23,1), TPosition(9,2));
  811. CompileAndCompare(one, two, &diff);
  812. }
  813. Y_UNIT_TEST(DiffrentLists) {
  814. const auto one = "((return '('7 '4 '('1 '3 '2))))";
  815. const auto two = "((let x '('1 '3))\n(let y '('7 '4 x))\n(return y))";
  816. const auto diff = std::make_pair(TPosition(20,1), TPosition(11,1));
  817. CompileAndCompare(one, two, &diff);
  818. }
  819. Y_UNIT_TEST(DiffrentCallables) {
  820. const auto one = "((return (- '4 (- '3 '2))))";
  821. const auto two = "((let x '3)\n(let y '2)\n(let z (- x y))\n(let r (+ '4 z))\n(return r))";
  822. const auto diff = std::make_pair(TPosition(11,1), TPosition(9,4));
  823. CompileAndCompare(one, two, &diff);
  824. }
  825. Y_UNIT_TEST(SwapArguments) {
  826. const auto one = "((let l (lambda '(x y) (+ x y)))\n(return (Apply l '7 '9)))";
  827. const auto two = "((return (Apply (lambda '(x y) (+ y x)) '7 '9)))";
  828. const auto diff = std::make_pair(TPosition(19,1), TPosition(29,1));
  829. CompileAndCompare(one, two, &diff);
  830. }
  831. }
  832. Y_UNIT_TEST_SUITE(TConvertToAst) {
  833. static TString CompileAndDisassemble(const TString& program, bool expectEqualExprs = true) {
  834. const auto astRes = ParseAst(program);
  835. UNIT_ASSERT(astRes.IsOk());
  836. TExprContext exprCtx;
  837. TExprNode::TPtr exprRoot;
  838. UNIT_ASSERT(CompileExpr(*astRes.Root, exprRoot, exprCtx, nullptr, nullptr));
  839. UNIT_ASSERT(exprRoot);
  840. const auto convRes = ConvertToAst(*exprRoot, exprCtx, 0, true);
  841. UNIT_ASSERT(convRes.IsOk());
  842. TExprContext exprCtx2;
  843. TExprNode::TPtr exprRoot2;
  844. auto compileOk = CompileExpr(*convRes.Root, exprRoot2, exprCtx2, nullptr, nullptr);
  845. exprCtx2.IssueManager.GetIssues().PrintTo(Cout);
  846. UNIT_ASSERT(compileOk);
  847. UNIT_ASSERT(exprRoot2);
  848. const TExprNode* node = exprRoot.Get();
  849. const TExprNode* node2 = exprRoot2.Get();
  850. bool equal = CompareExprTrees(node, node2);
  851. UNIT_ASSERT(equal == expectEqualExprs);
  852. return convRes.Root->ToString(TAstPrintFlags::PerLine | TAstPrintFlags::ShortQuote);
  853. }
  854. Y_UNIT_TEST(ManyLambdaWithCaptures) {
  855. const auto program = R"(
  856. (
  857. #comment
  858. (let mr_source (DataSource 'yt 'plato))
  859. (let x (Read! world mr_source (Key '('table (String 'Input))) '('key 'subkey 'value) '()))
  860. (let world (Left! x))
  861. (let table1 (Right! x))
  862. (let table1int (FlatMap table1
  863. (lambda '(item) (block '(
  864. (let intKey (FromString (Member item 'key) 'Int32))
  865. (let keyDiv100 (FlatMap intKey (lambda '(x) (/ x (Int32 '100)))))
  866. (let ret (Map keyDiv100 (lambda '(y) (block '(
  867. (let r '(y (Member item 'value)))
  868. (return r)
  869. )))))
  870. (return ret)
  871. )))
  872. ))
  873. (let table1intDebug (Map table1int (lambda '(it) (block '(
  874. (let s (Struct))
  875. (let s (AddMember s 'key (ToString (Nth it '0))))
  876. (let s (AddMember s 'subkey (String '.)))
  877. (let s (AddMember s 'value (Nth it '1)))
  878. (return s)
  879. )))))
  880. (let mr_sink (DataSink 'yt (quote plato)))
  881. (let world (Write! world mr_sink (Key '('table (String 'Output))) table1intDebug '('('mode 'append))))
  882. (let world (Commit! world mr_sink))
  883. (return world)
  884. )
  885. )";
  886. CompileAndDisassemble(program);
  887. }
  888. Y_UNIT_TEST(LambdaWithCaptureArgumentOfTopLambda) {
  889. const auto program = R"(
  890. (
  891. (let mr_source (DataSource 'yt 'plato))
  892. (let x (Read! world mr_source (Key '('table (String 'Input))) '('key 'subkey 'value) '()))
  893. (let world (Left! x))
  894. (let table1 (Right! x))
  895. (let table1low (FlatMap table1 (lambda '(item) (block '(
  896. (let intValueOpt (FromString (Member item 'key) 'Int32))
  897. (let ret (FlatMap intValueOpt (lambda '(item2) (block '(
  898. (return (ListIf (< item2 (Int32 '100)) item))
  899. )))))
  900. (return ret)
  901. )))))
  902. (let res_sink (DataSink 'result))
  903. (let data (AsList (String 'x)))
  904. (let world (Write! world res_sink (Key) table1low '()))
  905. (let world (Commit! world res_sink))
  906. (return world)
  907. )
  908. )";
  909. CompileAndDisassemble(program);
  910. }
  911. Y_UNIT_TEST(LambdaWithCapture) {
  912. const auto program = R"(
  913. (
  914. (let conf (Configure! world (DataSource 'yt '"$all") '"Attr" '"mapjoinlimit" '"1"))
  915. (let dsr (DataSink 'result))
  916. (let dsy (DataSink 'yt 'plato))
  917. (let co '('key 'subkey 'value))
  918. (let data (DataSource 'yt 'plato))
  919. (let string (DataType 'String))
  920. (let ostr (OptionalType string))
  921. (let struct (StructType '('key ostr) '('subkey ostr) '('value ostr)))
  922. (let scheme '('('"scheme" struct)))
  923. (let temp (MrTempTable dsy '"tmp/bb686f68-2245bd5f-2318fa4e-1" scheme))
  924. (let str (lambda '(arg) (Just (AsStruct '('key (Just (Member arg 'key))) '('subkey (Just (Member arg 'subkey))) '('value (Just (Member arg 'value)))))))
  925. (let map (MrMap! world dsy (Key '('table (String 'Input1))) co '() data temp '() str))
  926. (let tt (MrTempTable dsy '"tmp/7ae6459a-7382d1e7-7935c08e-2" scheme))
  927. (let map2 (MrMap! world dsy (Key '('table (String 'Input2))) co '() data tt '() str))
  928. (let s2 (StructType '('"a.key" string) '('"a.subkey" ostr) '('"a.value" ostr) '('"b.key" string) '('"b.subkey" ostr) '('"b.value" ostr)))
  929. (let mtt3 (MrTempTable dsy '"tmp/ecfc6738-59d47572-b9936849-3" '('('"scheme" s2))))
  930. (let tuple '('('"take" (Uint64 '"101"))))
  931. (let lmap (MrLMap! (Sync! map map2) dsy temp co '() data mtt3 '('('"limit" '(tuple))) (lambda '(arg) (block '(
  932. (let read (MrReadTable! world data tt co '()))
  933. (let key '('"key"))
  934. (let wtf '('"Hashed" '"One" '"Compact" '('"ItemsCount" '"4")))
  935. (let dict (ToDict (FilterNullMembers (MrTableContent read '()) key) (lambda '(arg) (Member arg '"key")) (lambda '(x) x) wtf))
  936. (let acols '('"key" '"a.key" '"subkey" '"a.subkey" '"value" '"a.value"))
  937. (let bcols '('"key" '"b.key" '"subkey" '"b.subkey" '"value" '"b.value"))
  938. (return (MapJoinCore arg dict 'Inner key acols bcols))
  939. )))))
  940. (let cols '('"a.key" '"a.subkey" '"a.value" '"b.key" '"b.subkey" '"b.value"))
  941. (let res (ResPull! conf dsr (Key) (Right! (MrReadTable! lmap data mtt3 cols tuple)) '('('type)) 'yt))
  942. (return (Commit! res dsr))
  943. )
  944. )";
  945. const auto disassembled = CompileAndDisassemble(program);
  946. UNIT_ASSERT(TString::npos != disassembled.find("'('key 'subkey 'value)"));
  947. UNIT_ASSERT_EQUAL(disassembled.find("'('key 'subkey 'value)"), disassembled.rfind("'('key 'subkey 'value)"));
  948. }
  949. Y_UNIT_TEST(ManyLambdasWithCommonCapture) {
  950. const auto program = R"(
  951. (
  952. (let c42 (+ (Int64 '40) (Int64 '2)))
  953. (let c100 (Int64 '100))
  954. (let l0 (lambda '(x) (- (* x c42) c42)))
  955. (let l1 (lambda '(y) (Apply l0 y)))
  956. (let l2 (lambda '(z) (+ (* c42) (Apply l0 c42))))
  957. (return (* (Apply l1 c100)(Apply l2 c100)))
  958. )
  959. )";
  960. const auto disassembled = CompileAndDisassemble(program);
  961. UNIT_ASSERT(TString::npos != disassembled.find("(+ (Int64 '40) (Int64 '2))"));
  962. UNIT_ASSERT_EQUAL(disassembled.find("(+ (Int64 '40) (Int64 '2))"), disassembled.rfind("(+ (Int64 '40) (Int64 '2))"));
  963. }
  964. Y_UNIT_TEST(CapturedUseInTopLevelAfrerLambda) {
  965. const auto program = R"(
  966. (
  967. (let $1 (DataSink 'result))
  968. (let $2 (DataSink '"yt" '"plato"))
  969. (let $3 (DataSource '"yt" '"plato"))
  970. (let $4 (TupleType (DataType 'Int64) (DataType 'Uint64)))
  971. (let $5 (MrTempTable $2 '"tmp/ecfc6738-59d47572-b9936849-3" '('('"scheme" (StructType '('"key" (DataType 'String)) '('"value" (StructType '('Avg1 (OptionalType $4)) '('Avg2 $4))))))))
  972. (let $6 (MrMapCombine! world $2 (Key '('table (String '"Input"))) '('"key" '"subkey") '() $3 $5 '() (lambda '($13) (Just (AsStruct '('"key" (Cast (Member $13 '"key") 'Int64)) '('"sub" (Unwrap (Cast (Member $13 '"subkey") 'Int64)))))) (lambda '($14) (Uint32 '"0")) (lambda '($15 $16) (block '(
  973. (let $18 (Uint64 '1))
  974. (let $17 (IfPresent (Member $16 '"key") (lambda '($19) (Just '($19 $18))) (Nothing (OptionalType (TupleType (DataType 'Int64) (DataType 'Uint64))))))
  975. (return (AsStruct '('Avg1 $17) '('Avg2 '((Member $16 '"sub") $18))))
  976. ))) (lambda '($20 $21 $22) (block '(
  977. (let $23 (IfPresent (Member $21 '"key") (lambda '($28) (block '(
  978. (let $29 (Uint64 '1))
  979. (return (Just '($28 $29)))
  980. ))) (Nothing (OptionalType (TupleType (DataType 'Int64) (DataType 'Uint64))))))
  981. (let $24 (IfPresent (Member $22 'Avg1) (lambda '($26) (IfPresent (Member $21 '"key") (lambda '($27) (Just '((+ (Nth $26 '0) $27) (Inc (Nth $26 '1))))) (Just $26))) $23))
  982. (let $25 (Member $22 'Avg2))
  983. (return (AsStruct '('Avg1 $24) '('Avg2 '((+ (Nth $25 '0) (Member $21 '"sub")) (Inc (Nth $25 '1))))))
  984. ))) (lambda '($30 $31) (Just (AsStruct '('"value" $31) '('"key" (String '"")))))))
  985. (return $6)
  986. )
  987. )";
  988. CompileAndDisassemble(program);
  989. }
  990. Y_UNIT_TEST(SelectCommonAncestor) {
  991. const auto program = R"(
  992. (
  993. (let $1 (DataSink 'result))
  994. (let $2 (DataSink '"yt" '"plato"))
  995. (let $3 '('"key" '"value"))
  996. (let $4 (DataSource '"yt" '"plato"))
  997. (let $5 (DataType 'String))
  998. (let $6 (OptionalType $5))
  999. (let $7 (MrTempTable $2 '"tmp/41c7eb81-87a9f8b6-70daa714-11" '('('"scheme" (StructType '('"key" $5) '('"value" (StructType '('Histogram0 $6) '('Histogram1 $6))))))))
  1000. (let $8 (Udf 'Histogram.AdaptiveWardHistogram_Create (Void) (VoidType) '"" (CallableType '() '((ResourceType '"Histogram.AdaptiveWard")) '((DataType 'Double)) '((DataType 'Double)) '((DataType 'Uint32)))))
  1001. (let $9 (Double '1.0))
  1002. (let $10 (Cast (Int32 '"1") 'Uint32))
  1003. (let $11 (Double '1.0))
  1004. (let $12 (Cast (Int32 '"1000000") 'Uint32))
  1005. (let $13 (MrMapCombine! world $2 (Key '('table (String '"Input"))) $3 '() $4 $7 '() (lambda '($21) (Just $21)) (lambda '($22) (Uint32 '"0")) (lambda '($23 $24) (AsStruct '('Histogram0 (FlatMap (Cast (Member $24 '"key") 'Double) (lambda '($25) (block '(
  1006. (let $26 '((DataType 'Double)))
  1007. (let $27 (CallableType '() '((ResourceType '"Histogram.AdaptiveWard")) $26 $26 '((DataType 'Uint32))))
  1008. (let $28 '((Unwrap (Cast (Member $24 '"key") 'Double)) $9 $10))
  1009. (return (Just (NamedApply $8 $28 (AsStruct) (Uint32 '"0"))))
  1010. ))))) '('Histogram1 (FlatMap (Cast (Member $24 '"value") 'Double) (lambda '($29) (block '(
  1011. (let $30 '((Unwrap (Cast (Member $24 '"value") 'Double)) $11 $12))
  1012. (return (Just (NamedApply $8 $30 (AsStruct) (Uint32 '"1"))))
  1013. ))))))) (lambda '($31 $32 $33) (block '(
  1014. (let $34 (Udf 'Histogram.AdaptiveWardHistogram_AddValue (Void) (VoidType) '"" (CallableType '() '((ResourceType '"Histogram.AdaptiveWard")) '((ResourceType '"Histogram.AdaptiveWard")) '((DataType 'Double)) '((DataType 'Double)))))
  1015. (let $35 (Uint32 '"0"))
  1016. (let $36 (IfPresent (Member $33 'Histogram0) (lambda '($39) (block '(
  1017. (let $40 (Cast (Member $32 '"key") 'Double))
  1018. (let $41 '((ResourceType '"Histogram.AdaptiveWard")))
  1019. (let $42 '((DataType 'Double)))
  1020. (let $43 (CallableType '() $41 $41 $42 $42))
  1021. (let $44 '($39 (Unwrap $40) $9))
  1022. (let $45 (NamedApply $34 $44 (AsStruct) $35))
  1023. (return (Just (If (Exists $40) $45 $39)))
  1024. ))) (FlatMap (Cast (Member $32 '"key") 'Double) (lambda '($46) (block '(
  1025. (let $47 '((Unwrap (Cast (Member $32 '"key") 'Double)) $9 $10))
  1026. (return (Just (NamedApply $8 $47 (AsStruct) $35)))
  1027. ))))))
  1028. (let $37 (Uint32 '"1"))
  1029. (let $38 (IfPresent (Member $33 'Histogram1) (lambda '($48) (block '(
  1030. (let $49 (Cast (Member $32 '"value") 'Double))
  1031. (let $50 '($48 (Unwrap $49) $11))
  1032. (let $51 (NamedApply $34 $50 (AsStruct) $37))
  1033. (return (Just (If (Exists $49) $51 $48)))
  1034. ))) (FlatMap (Cast (Member $32 '"value") 'Double) (lambda '($52) (block '(
  1035. (let $53 '((Unwrap (Cast (Member $32 '"value") 'Double)) $11 $12))
  1036. (return (Just (NamedApply $8 $53 (AsStruct) $37)))
  1037. ))))))
  1038. (return (AsStruct '('Histogram0 $36) '('Histogram1 $38)))
  1039. ))) (lambda '($54 $55) (block '(
  1040. (let $56 (lambda '($57) (block '(
  1041. (let $58 (CallableType '() '((DataType 'String)) '((ResourceType '"Histogram.AdaptiveWard"))))
  1042. (let $59 (Udf 'Histogram.AdaptiveWardHistogram_Serialize (Void) (VoidType) '"" $58))
  1043. (return (Just (Apply $59 $57)))
  1044. ))))
  1045. (return (Just (AsStruct '('"value" (AsStruct '('Histogram0 (FlatMap (Member $55 'Histogram0) $56)) '('Histogram1 (FlatMap (Member $55 'Histogram1) $56)))) '('"key" (String '"")))))
  1046. )))))
  1047. (let $14 (DataType 'Double))
  1048. (let $15 (OptionalType (StructType '('"Bins" (ListType (StructType '('"Frequency" $14) '('"Position" $14)))) '('"Max" $14) '('"Min" $14) '('"WeightsSum" $14))))
  1049. (let $16 (MrTempTable $2 '"tmp/b6d6c3ee-30bb3e55-ea0c48bc-12" '('('"scheme" (StructType '('"key_histogram" $15) '('"value_histogram" $15))))))
  1050. (let $17 (MrReduce! $13 $2 $7 $3 '() $4 $16 '('('"reduceBy" '('"key"))) (lambda '($60 $61) (block '(
  1051. (let $67 (Udf 'Histogram.AdaptiveWardHistogram_Deserialize (Void) (VoidType) '"" (CallableType '() '((ResourceType '"Histogram.AdaptiveWard")) '((DataType 'String)) '((DataType 'Uint32)))))
  1052. (let $62 (lambda '($68) (block '(
  1053. (let $69 (CallableType '() '((ResourceType '"Histogram.AdaptiveWard")) '((DataType 'String)) '((DataType 'Uint32))))
  1054. (return (Just (Apply $67 $68 $10)))
  1055. ))))
  1056. (let $63 (lambda '($70) (Just (Apply $67 $70 $12))))
  1057. (let $64 (Fold1 (FlatMap $61 (lambda '($65) (Just (Member $65 '"value")))) (lambda '($66) (block '(
  1058. (return (AsStruct '('Histogram0 (FlatMap (Member $66 'Histogram0) $62)) '('Histogram1 (FlatMap (Member $66 'Histogram1) $63))))
  1059. ))) (lambda '($71 $72) (block '(
  1060. (let $73 (lambda '($76 $77) (block '(
  1061. (let $78 '((ResourceType '"Histogram.AdaptiveWard")))
  1062. (let $79 (CallableType '() $78 $78 $78))
  1063. (let $80 (Udf 'Histogram.AdaptiveWardHistogram_Merge (Void) (VoidType) '"" $79))
  1064. (return (Apply $80 $76 $77))
  1065. ))))
  1066. (let $74 (OptionalReduce (FlatMap (Member $71 'Histogram0) $62) (Member $72 'Histogram0) $73))
  1067. (let $75 (OptionalReduce (FlatMap (Member $71 'Histogram1) $63) (Member $72 'Histogram1) $73))
  1068. (return (AsStruct '('Histogram0 $74) '('Histogram1 $75)))
  1069. )))))
  1070. (return (FlatMap $64 (lambda '($81) (block '(
  1071. (let $82 (lambda '($83) (block '(
  1072. (let $84 (DataType 'Double))
  1073. (let $85 (CallableType '() '((StructType '('"Bins" (ListType (StructType '('"Frequency" $84) '('"Position" $84)))) '('"Max" $84) '('"Min" $84) '('"WeightsSum" $84))) '((ResourceType '"Histogram.AdaptiveWard"))))
  1074. (let $86 (Udf 'Histogram.AdaptiveWardHistogram_GetResult (Void) (VoidType) '"" $85))
  1075. (return (Just (Apply $86 $83)))
  1076. ))))
  1077. (return (AsList (AsStruct '('"key_histogram" (FlatMap (Member $81 'Histogram0) $82)) '('"value_histogram" (FlatMap (Member $81 'Histogram1) $82)))))
  1078. )))))
  1079. )))))
  1080. (let $18 '('"key_histogram" '"value_histogram"))
  1081. (let $19 '('('type) '('autoref) '('columns $18)))
  1082. (let $20 (ResPull! world $1 (Key) (Right! (MrReadTable! $17 $4 $16 $18 '())) $19 '"yt"))
  1083. (return (Commit! (Commit! $20 $1) $2 '('('"epoch" '"1"))))
  1084. )
  1085. )";
  1086. CompileAndDisassemble(program);
  1087. }
  1088. Y_UNIT_TEST(Parameters) {
  1089. const auto program = R"(
  1090. (
  1091. (let $nameType (OptionalType (DataType 'String)))
  1092. (let $1 (Read! world (DataSource '"kikimr" '"local_ut") (Key '('table (String '"tmp/table"))) (Void) '()))
  1093. (let $2 (DataSink 'result))
  1094. (let $5 (Write! (Left! $1) $2 (Key) (FlatMap (Filter (Right! $1)
  1095. (lambda '($9) (Coalesce (And
  1096. (== (Member $9 '"Group") (Parameter '"$Group" (DataType 'Uint32)))
  1097. (== (Member $9 '"Name") (Parameter '"$Name" $nameType))) (Bool 'false))))
  1098. (lambda '($10) (AsList $10))) '('('type) '('autoref))))
  1099. (let $6 (Read! (Commit! $5 $2) (DataSource '"kikimr" '"local_ut")
  1100. (Key '('table (String '"tmp/table"))) (Void) '()))
  1101. (let $7 (DataSink 'result))
  1102. (let $8 (Write! (Left! $6) $7 (Key) (FlatMap (Filter (Right! $6)
  1103. (lambda '($11) (Coalesce (And
  1104. (== (Member $11 '"Group") (+ (Parameter '"$Group" (DataType 'Uint32)) (Int32 '"1")))
  1105. (== (Member $11 '"Name") (Coalesce (Parameter '"$Name" $nameType)
  1106. (String '"Empty")))) (Bool 'false))))
  1107. (lambda '($12) (AsList $12))) '('('type) '('autoref))))
  1108. (return (Commit! $8 $7))
  1109. )
  1110. )";
  1111. const auto disassembled = CompileAndDisassemble(program);
  1112. UNIT_ASSERT(TString::npos != disassembled.find("(declare $Group (DataType 'Uint32))"));
  1113. UNIT_ASSERT(TString::npos != disassembled.find("(declare $Name (OptionalType (DataType 'String)))"));
  1114. }
  1115. Y_UNIT_TEST(ParametersDifferentTypes) {
  1116. const auto program = R"(
  1117. (
  1118. (let $1 (Read! world (DataSource '"kikimr" '"local_ut") (Key '('table (String '"tmp/table"))) (Void) '()))
  1119. (let $2 (DataSink 'result))
  1120. (let $5 (Write! (Left! $1) $2 (Key) (FlatMap (Filter (Right! $1)
  1121. (lambda '($9) (Coalesce (And
  1122. (== (Member $9 '"Group") (Parameter '"$Group" (DataType 'Uint32)))
  1123. (== (Member $9 '"Name") (Parameter '"$Name" (OptionalType (DataType 'String))))) (Bool 'false))))
  1124. (lambda '($10) (AsList $10))) '('('type) '('autoref))))
  1125. (let $6 (Read! (Commit! $5 $2) (DataSource '"kikimr" '"local_ut")
  1126. (Key '('table (String '"tmp/table"))) (Void) '()))
  1127. (let $7 (DataSink 'result))
  1128. (let $8 (Write! (Left! $6) $7 (Key) (FlatMap (Filter (Right! $6)
  1129. (lambda '($11) (Coalesce (And
  1130. (== (Member $11 '"Group") (+ (Parameter '"$Group" (DataType 'Uint32)) (Int32 '"1")))
  1131. (== (Member $11 '"Name") (Coalesce (Parameter '"$Name" (OptionalType (DataType 'Int32)))
  1132. (String '"Empty")))) (Bool 'false))))
  1133. (lambda '($12) (AsList $12))) '('('type) '('autoref))))
  1134. (return (Commit! $8 $7))
  1135. )
  1136. )";
  1137. const auto disassembled = CompileAndDisassemble(program, false);
  1138. UNIT_ASSERT(TString::npos != disassembled.find("(declare $Group (DataType 'Uint32))"));
  1139. UNIT_ASSERT(TString::npos != disassembled.find("(declare $Name (OptionalType (DataType 'String)))"));
  1140. }
  1141. }
  1142. } // namespace NYql