#include "yql_expr.h" #include #include namespace NYql { Y_UNIT_TEST_SUITE(TCompileYqlExpr) { static TAstParseResult ParseAstWithCheck(const TStringBuf& s) { TAstParseResult res = ParseAst(s); res.Issues.PrintTo(Cout); UNIT_ASSERT(res.IsOk()); return res; } static void CompileExprWithCheck(TAstNode& root, TExprNode::TPtr& exprRoot, TExprContext& exprCtx, ui32 typeAnnotationIndex = Max()) { const bool success = CompileExpr(root, exprRoot, exprCtx, nullptr, nullptr, typeAnnotationIndex != Max(), typeAnnotationIndex); exprCtx.IssueManager.GetIssues().PrintTo(Cout); UNIT_ASSERT(success); UNIT_ASSERT_VALUES_EQUAL(exprRoot->GetState(), typeAnnotationIndex != Max() ? TExprNode::EState::TypeComplete : TExprNode::EState::Initial); } static void CompileExprWithCheck(TAstNode& root, TLibraryCohesion& cohesion, TExprContext& exprCtx) { const bool success = CompileExpr(root, cohesion, exprCtx); exprCtx.IssueManager.GetIssues().PrintTo(Cout); UNIT_ASSERT(success); } static bool ParseAndCompile(const TString& program) { TAstParseResult astRes = ParseAstWithCheck(program); TExprContext exprCtx; TExprNode::TPtr exprRoot; bool result = CompileExpr(*astRes.Root, exprRoot, exprCtx, nullptr, nullptr); exprCtx.IssueManager.GetIssues().PrintTo(Cout); return result; } Y_UNIT_TEST(TestNoReturn1) { auto s = "(\n" ")\n"; UNIT_ASSERT(false == ParseAndCompile(s)); } Y_UNIT_TEST(TestNoReturn2) { auto s = "(\n" "(let x 'y)\n" ")\n"; UNIT_ASSERT(false == ParseAndCompile(s)); } Y_UNIT_TEST(TestExportInsteadOfReturn) { const auto s = "# library\n" "(\n" " (let sqr (lambda '(x) (* x x)))\n" " (export sqr)\n" ")\n" ; UNIT_ASSERT(false == ParseAndCompile(s)); } Y_UNIT_TEST(TestLeftAfterReturn) { auto s = "(\n" "(return 'x)\n" "(let x 'y)\n" ")\n"; UNIT_ASSERT(false == ParseAndCompile(s)); } Y_UNIT_TEST(TestReturn) { auto s = "(\n" "(return world)\n" ")\n"; TAstParseResult astRes = ParseAstWithCheck(s); TExprContext exprCtx; TExprNode::TPtr exprRoot; CompileExprWithCheck(*astRes.Root, exprRoot, exprCtx); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Type(), TExprNode::World); } Y_UNIT_TEST(TestExport) { auto s = "(\n" "(let X 'Y)\n" "(let ex '42)\n" "(export ex)\n" "(export X)\n" ")\n"; TAstParseResult astRes = ParseAstWithCheck(s); TExprContext exprCtx; TLibraryCohesion cohesion; CompileExprWithCheck(*astRes.Root, cohesion, exprCtx); auto& exports = cohesion.Exports.Symbols(exprCtx); UNIT_ASSERT_VALUES_EQUAL(2U, exports.size()); UNIT_ASSERT_VALUES_EQUAL("42", exports["ex"]->Content()); UNIT_ASSERT_VALUES_EQUAL("Y", exports["X"]->Content()); } Y_UNIT_TEST(TestEmptyLib) { auto s = "(\n" "(let X 'Y)\n" "(let ex '42)\n" ")\n"; TAstParseResult astRes = ParseAstWithCheck(s); TExprContext exprCtx; TLibraryCohesion cohesion; CompileExprWithCheck(*astRes.Root, cohesion, exprCtx); UNIT_ASSERT(cohesion.Exports.Symbols().empty()); UNIT_ASSERT(cohesion.Imports.empty()); } Y_UNIT_TEST(TestArbitraryAtom) { auto s = "(\n" "(let x '\"\\x01\\x23\\x45\\x67\\x89\\xAB\\xCD\\xEF\")" "(return x)\n" ")\n"; TAstParseResult astRes = ParseAstWithCheck(s); TExprContext exprCtx; TExprNode::TPtr exprRoot; CompileExprWithCheck(*astRes.Root, exprRoot, exprCtx); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Type(), TExprNode::Atom); UNIT_ASSERT_STRINGS_EQUAL(HexEncode(exprRoot->Content()), "0123456789ABCDEF"); UNIT_ASSERT(exprRoot->Flags() & TNodeFlags::ArbitraryContent); auto ast = ConvertToAst(*exprRoot, exprCtx, TExprAnnotationFlags::None, true); TAstNode* xValue = ast.Root->GetChild(0)->GetChild(1)->GetChild(1); UNIT_ASSERT_STRINGS_EQUAL(HexEncode(TString(xValue->GetContent())), "0123456789ABCDEF"); UNIT_ASSERT(xValue->GetFlags() & TNodeFlags::ArbitraryContent); } Y_UNIT_TEST(TestBinaryAtom) { auto s = "(\n" "(let x 'x\"FEDCBA9876543210\")" "(return x)\n" ")\n"; TAstParseResult astRes = ParseAstWithCheck(s); TExprContext exprCtx; TExprNode::TPtr exprRoot; CompileExprWithCheck(*astRes.Root, exprRoot, exprCtx); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Type(), TExprNode::Atom); UNIT_ASSERT_STRINGS_EQUAL(HexEncode(exprRoot->Content()), "FEDCBA9876543210"); UNIT_ASSERT(exprRoot->Flags() & TNodeFlags::BinaryContent); auto ast = ConvertToAst(*exprRoot, exprCtx, TExprAnnotationFlags::None, true); TAstNode* xValue = ast.Root->GetChild(0)->GetChild(2)->GetChild(1); UNIT_ASSERT_STRINGS_EQUAL(HexEncode(TString(xValue->GetContent())), "FEDCBA9876543210"); UNIT_ASSERT(xValue->GetFlags() & TNodeFlags::BinaryContent); } Y_UNIT_TEST(TestLet) { auto s = "(\n" "(let x 'y)\n" "(return x)\n" ")\n"; TAstParseResult astRes = ParseAstWithCheck(s); TExprContext exprCtx; TExprNode::TPtr exprRoot; CompileExprWithCheck(*astRes.Root, exprRoot, exprCtx); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Type(), TExprNode::Atom); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Content(), "y"); } Y_UNIT_TEST(TestComplexQuote) { auto s = "(\n" "(let x 'a)\n" "(let y 'b)\n" "(let z (quote (x y)))\n" "(return z)\n" ")\n"; TAstParseResult astRes = ParseAstWithCheck(s); TExprContext exprCtx; TExprNode::TPtr exprRoot; CompileExprWithCheck(*astRes.Root, exprRoot, exprCtx); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Type(), TExprNode::List); UNIT_ASSERT_VALUES_EQUAL(exprRoot->ChildrenSize(), 2); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(0)->Type(), TExprNode::Atom); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(0)->Content(), "a"); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(1)->Type(), TExprNode::Atom); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(1)->Content(), "b"); } Y_UNIT_TEST(TestEmptyReturn) { auto s = "(\n" "(return)\n" ")\n"; UNIT_ASSERT(false == ParseAndCompile(s)); } Y_UNIT_TEST(TestManyReturn) { auto s = "(\n" "(return world world)\n" ")\n"; UNIT_ASSERT(false == ParseAndCompile(s)); } Y_UNIT_TEST(TestUnknownFunction) { auto s = "(\n" "(let a '2)\n" "(let x (+ a '3))\n" "(return x)\n" ")\n"; TAstParseResult astRes = ParseAstWithCheck(s); TExprContext exprCtx; TExprNode::TPtr exprRoot; CompileExprWithCheck(*astRes.Root, exprRoot, exprCtx); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Type(), TExprNode::Callable); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Content(), "+"); UNIT_ASSERT_VALUES_EQUAL(exprRoot->ChildrenSize(), 2); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(0)->Type(), TExprNode::Atom); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(0)->Content(), "2"); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(1)->Type(), TExprNode::Atom); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(1)->Content(), "3"); } Y_UNIT_TEST(TestReturnTwice) { auto s = "(\n" "(return)\n" "(return)\n" ")\n"; UNIT_ASSERT(false == ParseAndCompile(s)); } Y_UNIT_TEST(TestDeclareNonTop) { const auto s = R"( ( (let $1 (block '( (declare $param (DataType 'Uint32)) (return $param) ))) (return $1) ) )"; UNIT_ASSERT(false == ParseAndCompile(s)); } Y_UNIT_TEST(TestDeclareHideLet) { const auto s = R"( ( (let $name (Uint32 '10)) (declare $name (DataType 'Uint32)) (return $name) ) )"; UNIT_ASSERT(false == ParseAndCompile(s)); } Y_UNIT_TEST(TestDeclareBadName) { const auto s = R"( ( (declare $15 (DataType 'Uint32)) (return $15) ) )"; UNIT_ASSERT(false == ParseAndCompile(s)); } Y_UNIT_TEST(TestLetHideDeclare) { const auto s = R"( ( (declare $name (DataType 'Uint32)) (let $name (Uint32 '10)) (return $name) ) )"; TAstParseResult astRes = ParseAstWithCheck(s); TExprContext exprCtx; TExprNode::TPtr exprRoot; CompileExprWithCheck(*astRes.Root, exprRoot, exprCtx); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Type(), TExprNode::Callable); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Content(), "Uint32"); UNIT_ASSERT_VALUES_EQUAL(exprRoot->ChildrenSize(), 1); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(0)->Type(), TExprNode::Atom); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(0)->Content(), "10"); } Y_UNIT_TEST(TestDeclare) { const auto s = R"( ( (declare $param (DataType 'Uint32)) (return $param) ) )"; TAstParseResult astRes = ParseAstWithCheck(s); TExprContext exprCtx; TExprNode::TPtr exprRoot; CompileExprWithCheck(*astRes.Root, exprRoot, exprCtx); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Type(), TExprNode::Callable); UNIT_ASSERT_VALUES_EQUAL(exprRoot->ChildrenSize(), 2); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(0)->Type(), TExprNode::Atom); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(0)->Content(), "$param"); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(1)->Type(), TExprNode::Callable); UNIT_ASSERT_VALUES_EQUAL(exprRoot->Child(1)->Content(), "DataType"); } } Y_UNIT_TEST_SUITE(TCompareExprTrees) { void CompileAndCompare(const TString& one, const TString& two, const std::pair *const diffPositions = nullptr) { const auto progOne(ParseAst(one)), progTwo(ParseAst(two)); UNIT_ASSERT(progOne.IsOk() && progTwo.IsOk()); TExprContext ctxOne, ctxTwo; TExprNode::TPtr rootOne, rootTwo; UNIT_ASSERT(CompileExpr(*progOne.Root, rootOne, ctxOne, nullptr, nullptr)); UNIT_ASSERT(CompileExpr(*progTwo.Root, rootTwo, ctxTwo, nullptr, nullptr)); const TExprNode* diffOne = rootOne.Get(); const TExprNode* diffTwo = rootTwo.Get(); if (diffPositions) { UNIT_ASSERT(!CompareExprTrees(diffOne, diffTwo)); UNIT_ASSERT_EQUAL(ctxOne.GetPosition(diffOne->Pos()), diffPositions->first); UNIT_ASSERT_EQUAL(ctxTwo.GetPosition(diffTwo->Pos()), diffPositions->second); } else UNIT_ASSERT(CompareExprTrees(diffOne, diffTwo)); } Y_UNIT_TEST(BigGoodCompare) { const auto one = R"( ( (let $1 world) (let $2 (DataSource '"yt" '"plato")) (let $3 (MrTableRange '"statbox/yql-log" '"2016-05-25" '"2016-06-01")) (let $4 '('table $3)) (let $5 (Key $4)) (let $6 '('"method" '"uri" '"login" '"user_agent" '"millis")) (let $7 '()) (let $8 (Read! $1 $2 $5 $6 $7)) (let $9 (Left! $8)) (let $10 (DataSink 'result)) (let $11 (Key)) (let $12 (Right! $8)) (let $13 (lambda '($111) (block '( (let $113 (Member $111 '"method")) (let $114 (String '"POST")) (let $115 (== $113 $114)) (let $116 (Member $111 '"uri")) (let $117 (String '"/api/v2/operations")) (let $118 (== $116 $117)) (let $119 (Udf '"String.HasPrefix")) (let $120 (Member $111 '"uri")) (let $121 (String '"/api/v2/tutorials/")) (let $122 (Apply $119 $120 $121)) (let $123 (Or $118 $122)) (let $124 (Udf '"String.HasPrefix")) (let $125 (Member $111 '"uri")) (let $126 (String '"/api/v2/queries/")) (let $127 (Apply $124 $125 $126)) (let $128 (Or $123 $127)) (let $129 (And $115 $128)) (let $130 (Udf '"String.HasPrefix")) (let $131 (Member $111 '"uri")) (let $132 (String '"/api/v2/table_data_async")) (let $133 (Apply $130 $131 $132)) (let $134 (Or $129 $133)) (let $135 (Udf '"String.HasPrefix")) (let $136 (Member $111 '"login")) (let $137 (String '"robot-")) (let $138 (Apply $135 $136 $137)) (let $139 (Not $138)) (let $140 (And $134 $139)) (let $141 (Bool 'false)) (let $142 (Coalesce $140 $141)) (return $142) )))) (let $14 (Filter $12 $13)) (let $15 (lambda '($143) (block '( (let $145 (Struct)) (let $146 (Member $143 '"login")) (let $147 (AddMember $145 '"login" $146)) (let $148 (Udf '"String.HasPrefix")) (let $149 (Member $143 '"user_agent")) (let $150 (String '"YQL ")) (let $151 (Apply $148 $149 $150)) (let $152 (Bool 'false)) (let $153 (Coalesce $151 $152)) (let $154 (Udf '"String.SplitToList")) (let $155 (Member $143 '"user_agent")) (let $156 (String '" ")) (let $157 (Apply $154 $155 $156)) (let $158 (Int64 '"1")) (let $159 (SqlAccess 'dict $157 $158)) (let $160 (String '"CLI")) (let $161 (== $159 $160)) (let $162 (Bool 'false)) (let $163 (Coalesce $161 $162)) (let $164 (String '"CLI")) (let $165 (String '"API")) (let $166 (If $163 $164 $165)) (let $167 (String '"Web UI")) (let $168 (If $153 $166 $167)) (let $169 (AddMember $147 '"client_type" $168)) (let $170 (Udf '"DateTime.ToDate")) (let $171 (Udf '"DateTime.StartOfWeek")) (let $172 (Udf '"DateTime.FromMilliSeconds")) (let $173 (Member $143 '"millis")) (let $174 (Cast $173 'Uint64)) (let $175 (Apply $172 $174)) (let $176 (Apply $171 $175)) (let $177 (Apply $170 $176)) (let $178 (String '"")) (let $179 (Coalesce $177 $178)) (let $180 (String '" - ")) (let $181 (Concat $179 $180)) (let $182 (Udf '"DateTime.ToDate")) (let $183 (Udf '"DateTime.StartOfWeek")) (let $184 (Udf '"DateTime.FromMilliSeconds")) (let $185 (Member $143 '"millis")) (let $186 (Cast $185 'Uint64)) (let $187 (Apply $184 $186)) (let $188 (Apply $183 $187)) (let $189 (Udf '"DateTime.FromDays")) (let $190 (Int64 '"6")) (let $191 (Apply $189 $190)) (let $192 (+ $188 $191)) (let $193 (Apply $182 $192)) (let $194 (String '"")) (let $195 (Coalesce $193 $194)) (let $196 (Concat $181 $195)) (let $197 (AddMember $169 '"week" $196)) (let $198 (AsList $197)) (return $198) )))) )" R"( (let $16 (FlatMap $14 $15)) (let $17 '('"client_type" '"week")) (let $18 (lambda '($199 $200) (block '( (let $202 (lambda '($205 $206 $207) (block '( (let $209 (ListItemType $205)) (let $210 (lambda '($223) (block '( (let $212 (ListItemType $205)) (let $213 (InstanceOf $212)) (let $214 (Apply $206 $213)) (let $215 (TypeOf $214)) (let $216 (ListType $215)) (let $217 (Apply $207 $216)) (let $225 (NthArg '1 $217)) (let $226 (Apply $206 $223)) (let $227 (Apply $225 $226)) (return $227) )))) (let $211 (lambda '($228 $229) (block '( (let $212 (ListItemType $205)) (let $213 (InstanceOf $212)) (let $214 (Apply $206 $213)) (let $215 (TypeOf $214)) (let $216 (ListType $215)) (let $217 (Apply $207 $216)) (let $231 (NthArg '2 $217)) (let $232 (Apply $206 $228)) (let $233 (Apply $231 $232 $229)) (return $233) )))) (let $212 (ListItemType $205)) (let $213 (InstanceOf $212)) (let $214 (Apply $206 $213)) (let $215 (TypeOf $214)) (let $216 (ListType $215)) (let $217 (Apply $207 $216)) (let $218 (NthArg '3 $217)) (let $219 (NthArg '4 $217)) (let $220 (NthArg '5 $217)) (let $221 (NthArg '6 $217)) (let $222 (AggregationTraits $209 $210 $211 $218 $219 $220 $221)) (return $222) )))) (let $203 (lambda '($234) (block '( (let $236 (ListItemType $234)) (let $237 (lambda '($244) (block '( (let $246 (AggrCountInit $244)) (return $246) )))) (let $238 (lambda '($247 $248) (block '( (let $250 (AggrCountUpdate $247 $248)) (return $250) )))) (let $239 (lambda '($251) (block '( (return $251) )))) (let $240 (lambda '($253) (block '( (return $253) )))) (let $241 (lambda '($255 $256) (block '( (let $258 (+ $255 $256)) (return $258) )))) (let $242 (lambda '($259) (block '( (return $259) )))) (let $243 (AggregationTraits $236 $237 $238 $239 $240 $241 $242)) (return $243) )))) (let $204 (Apply $202 $199 $200 $203)) (return $204) )))) (let $19 (TypeOf $16)) (let $20 (ListItemType $19)) (let $21 (StructMemberType $20 '"login")) (let $22 (ListType $21)) (let $23 (lambda '($261) (block '( (return $261) )))) (let $24 (Apply $18 $22 $23)) (let $25 '('Count1 $24 '"login")) (let $26 (TypeOf $16)) (let $27 (lambda '($263) (block '( (let $265 (Void)) (return $265) )))) (let $28 (Apply $18 $26 $27)) (let $29 '('Count2 $28)) (let $30 (TypeOf $16)) (let $31 (lambda '($266) (block '( (let $268 (Void)) (return $268) )))) (let $32 (Apply $18 $30 $31)) (let $33 '('Count3 $32)) (let $34 (TypeOf $16)) (let $35 (ListItemType $34)) (let $36 (StructMemberType $35 '"login")) (let $37 (ListType $36)) (let $38 (lambda '($269) (block '( (return $269) )))) (let $39 (Apply $18 $37 $38)) (let $40 '('Count4 $39 '"login")) (let $41 '($25 $29 $33 $40)) (let $42 (Aggregate $16 $17 $41)) (let $43 (lambda '($271) (block '( (let $273 (Struct)) (let $274 (Member $271 '"week")) (let $275 (AddMember $273 '"week" $274)) (let $276 (Member $271 '"client_type")) (let $277 (AddMember $275 '"client_type" $276)) (let $278 (Member $271 'Count1)) (let $279 (AddMember $277 '"users_count" $278)) (let $280 (Member $271 'Count2)) (let $281 (AddMember $279 '"operations_count" $280)) (let $282 (Member $271 'Count3)) (let $283 (Member $271 'Count4)) (let $284 (/ $282 $283)) (let $285 (AddMember $281 '"operations_per_user" $284)) (let $286 (AsList $285)) (return $286) )))) (let $44 (FlatMap $42 $43)) (let $45 (Bool 'false)) (let $46 (Bool 'false)) (let $47 '($45 $46)) (let $48 (lambda '($287) (block '( (let $289 (Member $287 '"week")) (let $290 (Member $287 '"users_count")) (let $291 '($289 $290)) (return $291) )))) (let $49 (Sort $44 $47 $48)) (let $50 '('type)) (let $51 '('autoref)) (let $52 '('"week" '"client_type" '"users_count" '"operations_count" '"operations_per_user")) (let $53 '('columns $52)) (let $54 '($50 $51 $53)) (let $55 (Write! $9 $10 $11 $49 $54)) (let $56 (Commit! $55 $10)) (let $57 (DataSource '"yt" '"plato")) (let $58 (MrTableRange '"statbox/yql-log" '"2016-05-25" '"2016-06-01")) (let $59 '('table $58)) (let $60 (Key $59)) (let $61 '('"method" '"uri" '"login" '"user_agent" '"millis")) (let $62 '()) (let $63 (Read! $56 $57 $60 $61 $62)) (let $64 (Left! $63)) (let $65 (DataSink 'result)) (let $66 (Key)) (let $67 (Right! $63)) (let $68 (lambda '($292) (block '( (let $294 (Member $292 '"method")) (let $295 (String '"POST")) (let $296 (== $294 $295)) (let $297 (Member $292 '"uri")) (let $298 (String '"/api/v2/operations")) (let $299 (== $297 $298)) (let $300 (Udf '"String.HasPrefix")) (let $301 (Member $292 '"uri")) (let $302 (String '"/api/v2/tutorials/")) (let $303 (Apply $300 $301 $302)) (let $304 (Or $299 $303)) (let $305 (Udf '"String.HasPrefix")) (let $306 (Member $292 '"uri")) (let $307 (String '"/api/v2/queries/")) (let $308 (Apply $305 $306 $307)) (let $309 (Or $304 $308)) (let $310 (And $296 $309)) (let $311 (Udf '"String.HasPrefix")) (let $312 (Member $292 '"uri")) (let $313 (String '"/api/v2/table_data_async")) (let $314 (Apply $311 $312 $313)) (let $315 (Or $310 $314)) (let $316 (Udf '"String.HasPrefix")) (let $317 (Member $292 '"login")) (let $318 (String '"robot-")) (let $319 (Apply $316 $317 $318)) (let $320 (Not $319)) (let $321 (And $315 $320)) (let $322 (Bool 'false)) (let $323 (Coalesce $321 $322)) (return $323) )))) (let $69 (Filter $67 $68)) (let $70 (lambda '($324) (block '( (let $326 (Struct)) (let $327 (Member $324 '"login")) (let $328 (AddMember $326 '"login" $327)) (let $329 (Udf '"String.HasPrefix")) (let $330 (Member $324 '"user_agent")) (let $331 (String '"YQL ")) (let $332 (Apply $329 $330 $331)) (let $333 (Bool 'false)) (let $334 (Coalesce $332 $333)) (let $335 (Udf '"String.SplitToList")) (let $336 (Member $324 '"user_agent")) (let $337 (String '" ")) (let $338 (Apply $335 $336 $337)) (let $339 (Int64 '"1")) (let $340 (SqlAccess 'dict $338 $339)) (let $341 (String '"CLI")) (let $342 (== $340 $341)) (let $343 (Bool 'false)) (let $344 (Coalesce $342 $343)) (let $345 (String '"CLI")) (let $346 (String '"API")) (let $347 (If $344 $345 $346)) (let $348 (String '"Web UI")) (let $349 (If $334 $347 $348)) (let $350 (AddMember $328 '"client_type" $349)) (let $351 (Udf '"DateTime.ToDate")) (let $352 (Udf '"DateTime.StartOfWeek")) (let $353 (Udf '"DateTime.FromMilliSeconds")) (let $354 (Member $324 '"millis")) (let $355 (Cast $354 'Uint64)) (let $356 (Apply $353 $355)) (let $357 (Apply $352 $356)) (let $358 (Apply $351 $357)) (let $359 (String '"")) (let $360 (Coalesce $358 $359)) (let $361 (String '" - ")) (let $362 (Concat $360 $361)) (let $363 (Udf '"DateTime.ToDate")) (let $364 (Udf '"DateTime.StartOfWeek")) (let $365 (Udf '"DateTime.FromMilliSeconds")) (let $366 (Member $324 '"millis")) (let $367 (Cast $366 'Uint64)) (let $368 (Apply $365 $367)) (let $369 (Apply $364 $368)) (let $370 (Udf '"DateTime.FromDays")) (let $371 (Int64 '"6")) (let $372 (Apply $370 $371)) (let $373 (+ $369 $372)) (let $374 (Apply $363 $373)) (let $375 (String '"")) (let $376 (Coalesce $374 $375)) (let $377 (Concat $362 $376)) (let $378 (AddMember $350 '"week" $377)) (let $379 (AsList $378)) (return $379) )))) (let $71 (FlatMap $69 $70)) (let $72 '('"week")) (let $73 (TypeOf $71)) (let $74 (ListItemType $73)) (let $75 (StructMemberType $74 '"login")) (let $76 (ListType $75)) (let $77 (lambda '($380) (block '( (return $380) )))) (let $78 (Apply $18 $76 $77)) (let $79 '('Count6 $78 '"login")) (let $80 (TypeOf $71)) (let $81 (lambda '($382) (block '( (let $384 (Void)) (return $384) )))) (let $82 (Apply $18 $80 $81)) (let $83 '('Count7 $82)) (let $84 (TypeOf $71)) (let $85 (lambda '($385) (block '( (let $387 (Void)) (return $387) )))) (let $86 (Apply $18 $84 $85)) (let $87 '('Count8 $86)) (let $88 (TypeOf $71)) (let $89 (ListItemType $88)) (let $90 (StructMemberType $89 '"login")) (let $91 (ListType $90)) (let $92 (lambda '($388) (block '( (return $388) )))) (let $93 (Apply $18 $91 $92)) (let $94 '('Count9 $93 '"login")) (let $95 '($79 $83 $87 $94)) (let $96 (Aggregate $71 $72 $95)) (let $97 (lambda '($390) (block '( (let $392 (Struct)) (let $393 (Member $390 '"week")) (let $394 (AddMember $392 '"week" $393)) (let $395 (Member $390 'Count6)) (let $396 (AddMember $394 '"users_count" $395)) (let $397 (Member $390 'Count7)) (let $398 (AddMember $396 '"operations_count" $397)) (let $399 (Member $390 'Count8)) (let $400 (Member $390 'Count9)) (let $401 (/ $399 $400)) (let $402 (AddMember $398 '"operations_per_user" $401)) (let $403 (AsList $402)) (return $403) )))) (let $98 (FlatMap $96 $97)) (let $99 (Bool 'false)) (let $100 (lambda '($404) (block '( (let $406 (Member $404 '"week")) (return $406) )))) (let $101 (Sort $98 $99 $100)) (let $102 '('type)) (let $103 '('autoref)) (let $104 '('"week" '"users_count" '"operations_count" '"operations_per_user")) (let $105 '('columns $104)) (let $106 '($102 $103 $105)) (let $107 (Write! $64 $65 $66 $101 $106)) (let $108 (Commit! $107 $65)) (let $109 (DataSink '"yt" '"plato")) (let $110 (Commit! $108 $109)) (return $110) ) )"; const auto two = R"( ( (let $1 (MrTableRange '"statbox/yql-log" '"2016-05-25" '"2016-06-01")) (let $2 '('"method" '"uri" '"login" '"user_agent" '"millis")) (let $3 (Read! world (DataSource '"yt" '"plato") (Key '('table $1)) $2 '())) (let $4 (DataSink 'result)) (let $5 (FlatMap (Filter (Right! $3) (lambda '($36) (block '( (let $37 (Apply (Udf '"String.HasPrefix") (Member $36 '"uri") (String '"/api/v2/tutorials/"))) (let $38 (Apply (Udf '"String.HasPrefix") (Member $36 '"uri") (String '"/api/v2/queries/"))) (let $39 (Apply (Udf '"String.HasPrefix") (Member $36 '"uri") (String '"/api/v2/table_data_async"))) (let $40 (Apply (Udf '"String.HasPrefix") (Member $36 '"login") (String '"robot-"))) (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))) )))) (lambda '($41) (block '( (let $42 (AddMember (Struct) '"login" (Member $41 '"login"))) (let $43 (Apply (Udf '"String.HasPrefix") (Member $41 '"user_agent") (String '"YQL "))) (let $44 (Apply (Udf '"String.SplitToList") (Member $41 '"user_agent") (String '" "))) (let $45 (SqlAccess 'dict $44 (Int64 '"1"))) (let $46 (If (Coalesce (== $45 (String '"CLI")) (Bool 'false)) (String '"CLI") (String '"API"))) (let $47 (If (Coalesce $43 (Bool 'false)) $46 (String '"Web UI"))) (let $48 (AddMember $42 '"client_type" $47)) (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 '""))))) (return (AsList $49)) ))))) (let $6 (lambda '($50 $51) (block '( (let $52 (Apply (lambda '($53 $54 $55) (block '( (let $57 (Apply $55 (ListType (TypeOf (Apply $54 (InstanceOf (ListItemType $53))))))) (let $58 (AggregationTraits (ListItemType $53) (lambda '($59) (block '( (let $57 (Apply $55 (ListType (TypeOf (Apply $54 (InstanceOf (ListItemType $53))))))) (return (Apply (NthArg '1 $57) (Apply $54 $59))) ))) (lambda '($60 $61) (block '( (let $57 (Apply $55 (ListType (TypeOf (Apply $54 (InstanceOf (ListItemType $53))))))) (let $62 (Apply (NthArg '2 $57) (Apply $54 $60) $61)) (return $62) ))) (NthArg '3 $57) (NthArg '4 $57) (NthArg '5 $57) (NthArg '6 $57))) (return $58) ))) $50 $51 (lambda '($63) (block '( (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))) (return $64) ))))) (return $52) )))) (let $7 (Apply $6 (ListType (StructMemberType (ListItemType (TypeOf $5)) '"login")) (lambda '($73) $73))) (let $8 '('Count1 $7 '"login")) (let $9 (Apply $6 (TypeOf $5) (lambda '($74) (Void)))) (let $10 (Apply $6 (TypeOf $5) (lambda '($75) (Void)))) (let $11 (Apply $6 (ListType (StructMemberType (ListItemType (TypeOf $5)) '"login")) (lambda '($76) $76))) (let $12 '('Count4 $11 '"login")) (let $13 '($8 '('Count2 $9) '('Count3 $10) $12)) (let $14 (Aggregate $5 '('"client_type" '"week") $13)) (let $15 (Sort (FlatMap $14 (lambda '($77) (block '( (let $78 (AddMember (Struct) '"week" (Member $77 '"week"))) (let $79 (AddMember $78 '"client_type" (Member $77 '"client_type"))) (let $80 (AddMember $79 '"users_count" (Member $77 'Count1))) (let $81 (AddMember $80 '"operations_count" (Member $77 'Count2))) (let $82 (AddMember $81 '"operations_per_user" (/ (Member $77 'Count3) (Member $77 'Count4)))) (return (AsList $82)) )))) '((Bool 'false) (Bool 'false)) (lambda '($83) '((Member $83 '"week") (Member $83 '"users_count"))))) (let $16 '('"week" '"client_type" '"users_count" '"operations_count" '"operations_per_user")) (let $17 '('('type) '('autoref) '('columns $16))) (let $18 (Write! (Left! $3) $4 (Key) $15 $17)) (let $19 (MrTableRange '"statbox/yql-log" '"2016-05-25" '"2016-06-01")) (let $20 '('"method" '"uri" '"login" '"user_agent" '"millis")) (let $21 (Read! (Commit! $18 $4) (DataSource '"yt" '"plato") (Key '('table $19)) $20 '())) (let $22 (DataSink 'result)) (let $23 (FlatMap (Filter (Right! $21) (lambda '($84) (block '( (let $85 (Apply (Udf '"String.HasPrefix") (Member $84 '"uri") (String '"/api/v2/tutorials/"))) (let $86 (Apply (Udf '"String.HasPrefix") (Member $84 '"uri") (String '"/api/v2/queries/"))) (let $87 (Apply (Udf '"String.HasPrefix") (Member $84 '"uri") (String '"/api/v2/table_data_async"))) (let $88 (Apply (Udf '"String.HasPrefix") (Member $84 '"login") (String '"robot-"))) (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))) )))) (lambda '($89) (block '( (let $90 (AddMember (Struct) '"login" (Member $89 '"login"))) (let $91 (Apply (Udf '"String.HasPrefix") (Member $89 '"user_agent") (String '"YQL "))) (let $92 (Apply (Udf '"String.SplitToList") (Member $89 '"user_agent") (String '" "))) (let $93 (SqlAccess 'dict $92 (Int64 '"1"))) (let $94 (If (Coalesce (== $93 (String '"CLI")) (Bool 'false)) (String '"CLI") (String '"API"))) (let $95 (If (Coalesce $91 (Bool 'false)) $94 (String '"Web UI"))) (let $96 (AddMember $90 '"client_type" $95)) (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 '""))))) (return (AsList $97)) ))))) (let $24 (Apply $6 (ListType (StructMemberType (ListItemType (TypeOf $23)) '"login")) (lambda '($98) $98))) (let $25 '('Count6 $24 '"login")) (let $26 (Apply $6 (TypeOf $23) (lambda '($99) (Void)))) (let $27 (Apply $6 (TypeOf $23) (lambda '($100) (Void)))) (let $28 (Apply $6 (ListType (StructMemberType (ListItemType (TypeOf $23)) '"login")) (lambda '($101) $101))) (let $29 '('Count9 $28 '"login")) (let $30 '($25 '('Count7 $26) '('Count8 $27) $29)) (let $31 (Aggregate $23 '('"week") $30)) (let $32 (Sort (FlatMap $31 (lambda '($102) (block '( (let $103 (AddMember (Struct) '"week" (Member $102 '"week"))) (let $104 (AddMember $103 '"users_count" (Member $102 'Count6))) (let $105 (AddMember $104 '"operations_count" (Member $102 'Count7))) (let $106 (AddMember $105 '"operations_per_user" (/ (Member $102 'Count8) (Member $102 'Count9)))) (return (AsList $106)) )))) (Bool 'false) (lambda '($107) (Member $107 '"week")))) (let $33 '('"week" '"users_count" '"operations_count" '"operations_per_user")) (let $34 '('('type) '('autoref) '('columns $33))) (let $35 (Write! (Left! $21) $22 (Key) $32 $34)) (return (Commit! (Commit! $35 $22) (DataSink '"yt" '"plato"))) ) )"; CompileAndCompare(one, two); } Y_UNIT_TEST(DiffrentAtoms) { const auto one = "((return (+ '4 (- '3 '2))))"; const auto two = "((let x '3)\n(let y '1)\n(let z (- x y))\n(let r (+ '4 z))\n(return r))"; const auto diff = std::make_pair(TPosition(23,1), TPosition(9,2)); CompileAndCompare(one, two, &diff); } Y_UNIT_TEST(DiffrentLists) { const auto one = "((return '('7 '4 '('1 '3 '2))))"; const auto two = "((let x '('1 '3))\n(let y '('7 '4 x))\n(return y))"; const auto diff = std::make_pair(TPosition(20,1), TPosition(11,1)); CompileAndCompare(one, two, &diff); } Y_UNIT_TEST(DiffrentCallables) { const auto one = "((return (- '4 (- '3 '2))))"; const auto two = "((let x '3)\n(let y '2)\n(let z (- x y))\n(let r (+ '4 z))\n(return r))"; const auto diff = std::make_pair(TPosition(11,1), TPosition(9,4)); CompileAndCompare(one, two, &diff); } Y_UNIT_TEST(SwapArguments) { const auto one = "((let l (lambda '(x y) (+ x y)))\n(return (Apply l '7 '9)))"; const auto two = "((return (Apply (lambda '(x y) (+ y x)) '7 '9)))"; const auto diff = std::make_pair(TPosition(19,1), TPosition(29,1)); CompileAndCompare(one, two, &diff); } } Y_UNIT_TEST_SUITE(TConvertToAst) { static TString CompileAndDisassemble(const TString& program, bool expectEqualExprs = true) { const auto astRes = ParseAst(program); UNIT_ASSERT(astRes.IsOk()); TExprContext exprCtx; TExprNode::TPtr exprRoot; UNIT_ASSERT(CompileExpr(*astRes.Root, exprRoot, exprCtx, nullptr, nullptr)); UNIT_ASSERT(exprRoot); const auto convRes = ConvertToAst(*exprRoot, exprCtx, 0, true); UNIT_ASSERT(convRes.IsOk()); TExprContext exprCtx2; TExprNode::TPtr exprRoot2; auto compileOk = CompileExpr(*convRes.Root, exprRoot2, exprCtx2, nullptr, nullptr); exprCtx2.IssueManager.GetIssues().PrintTo(Cout); UNIT_ASSERT(compileOk); UNIT_ASSERT(exprRoot2); const TExprNode* node = exprRoot.Get(); const TExprNode* node2 = exprRoot2.Get(); bool equal = CompareExprTrees(node, node2); UNIT_ASSERT(equal == expectEqualExprs); return convRes.Root->ToString(TAstPrintFlags::PerLine | TAstPrintFlags::ShortQuote); } Y_UNIT_TEST(ManyLambdaWithCaptures) { const auto program = R"( ( #comment (let mr_source (DataSource 'yt 'plato)) (let x (Read! world mr_source (Key '('table (String 'Input))) '('key 'subkey 'value) '())) (let world (Left! x)) (let table1 (Right! x)) (let table1int (FlatMap table1 (lambda '(item) (block '( (let intKey (FromString (Member item 'key) 'Int32)) (let keyDiv100 (FlatMap intKey (lambda '(x) (/ x (Int32 '100))))) (let ret (Map keyDiv100 (lambda '(y) (block '( (let r '(y (Member item 'value))) (return r) ))))) (return ret) ))) )) (let table1intDebug (Map table1int (lambda '(it) (block '( (let s (Struct)) (let s (AddMember s 'key (ToString (Nth it '0)))) (let s (AddMember s 'subkey (String '.))) (let s (AddMember s 'value (Nth it '1))) (return s) ))))) (let mr_sink (DataSink 'yt (quote plato))) (let world (Write! world mr_sink (Key '('table (String 'Output))) table1intDebug '('('mode 'append)))) (let world (Commit! world mr_sink)) (return world) ) )"; CompileAndDisassemble(program); } Y_UNIT_TEST(LambdaWithCaptureArgumentOfTopLambda) { const auto program = R"( ( (let mr_source (DataSource 'yt 'plato)) (let x (Read! world mr_source (Key '('table (String 'Input))) '('key 'subkey 'value) '())) (let world (Left! x)) (let table1 (Right! x)) (let table1low (FlatMap table1 (lambda '(item) (block '( (let intValueOpt (FromString (Member item 'key) 'Int32)) (let ret (FlatMap intValueOpt (lambda '(item2) (block '( (return (ListIf (< item2 (Int32 '100)) item)) ))))) (return ret) ))))) (let res_sink (DataSink 'result)) (let data (AsList (String 'x))) (let world (Write! world res_sink (Key) table1low '())) (let world (Commit! world res_sink)) (return world) ) )"; CompileAndDisassemble(program); } Y_UNIT_TEST(LambdaWithCapture) { const auto program = R"( ( (let conf (Configure! world (DataSource 'yt '"$all") '"Attr" '"mapjoinlimit" '"1")) (let dsr (DataSink 'result)) (let dsy (DataSink 'yt 'plato)) (let co '('key 'subkey 'value)) (let data (DataSource 'yt 'plato)) (let string (DataType 'String)) (let ostr (OptionalType string)) (let struct (StructType '('key ostr) '('subkey ostr) '('value ostr))) (let scheme '('('"scheme" struct))) (let temp (MrTempTable dsy '"tmp/bb686f68-2245bd5f-2318fa4e-1" scheme)) (let str (lambda '(arg) (Just (AsStruct '('key (Just (Member arg 'key))) '('subkey (Just (Member arg 'subkey))) '('value (Just (Member arg 'value))))))) (let map (MrMap! world dsy (Key '('table (String 'Input1))) co '() data temp '() str)) (let tt (MrTempTable dsy '"tmp/7ae6459a-7382d1e7-7935c08e-2" scheme)) (let map2 (MrMap! world dsy (Key '('table (String 'Input2))) co '() data tt '() str)) (let s2 (StructType '('"a.key" string) '('"a.subkey" ostr) '('"a.value" ostr) '('"b.key" string) '('"b.subkey" ostr) '('"b.value" ostr))) (let mtt3 (MrTempTable dsy '"tmp/ecfc6738-59d47572-b9936849-3" '('('"scheme" s2)))) (let tuple '('('"take" (Uint64 '"101")))) (let lmap (MrLMap! (Sync! map map2) dsy temp co '() data mtt3 '('('"limit" '(tuple))) (lambda '(arg) (block '( (let read (MrReadTable! world data tt co '())) (let key '('"key")) (let wtf '('"Hashed" '"One" '"Compact" '('"ItemsCount" '"4"))) (let dict (ToDict (FilterNullMembers (MrTableContent read '()) key) (lambda '(arg) (Member arg '"key")) (lambda '(x) x) wtf)) (let acols '('"key" '"a.key" '"subkey" '"a.subkey" '"value" '"a.value")) (let bcols '('"key" '"b.key" '"subkey" '"b.subkey" '"value" '"b.value")) (return (MapJoinCore arg dict 'Inner key acols bcols)) ))))) (let cols '('"a.key" '"a.subkey" '"a.value" '"b.key" '"b.subkey" '"b.value")) (let res (ResPull! conf dsr (Key) (Right! (MrReadTable! lmap data mtt3 cols tuple)) '('('type)) 'yt)) (return (Commit! res dsr)) ) )"; const auto disassembled = CompileAndDisassemble(program); UNIT_ASSERT(TString::npos != disassembled.find("'('key 'subkey 'value)")); UNIT_ASSERT_EQUAL(disassembled.find("'('key 'subkey 'value)"), disassembled.rfind("'('key 'subkey 'value)")); } Y_UNIT_TEST(ManyLambdasWithCommonCapture) { const auto program = R"( ( (let c42 (+ (Int64 '40) (Int64 '2))) (let c100 (Int64 '100)) (let l0 (lambda '(x) (- (* x c42) c42))) (let l1 (lambda '(y) (Apply l0 y))) (let l2 (lambda '(z) (+ (* c42) (Apply l0 c42)))) (return (* (Apply l1 c100)(Apply l2 c100))) ) )"; const auto disassembled = CompileAndDisassemble(program); UNIT_ASSERT(TString::npos != disassembled.find("(+ (Int64 '40) (Int64 '2))")); UNIT_ASSERT_EQUAL(disassembled.find("(+ (Int64 '40) (Int64 '2))"), disassembled.rfind("(+ (Int64 '40) (Int64 '2))")); } Y_UNIT_TEST(CapturedUseInTopLevelAfrerLambda) { const auto program = R"( ( (let $1 (DataSink 'result)) (let $2 (DataSink '"yt" '"plato")) (let $3 (DataSource '"yt" '"plato")) (let $4 (TupleType (DataType 'Int64) (DataType 'Uint64))) (let $5 (MrTempTable $2 '"tmp/ecfc6738-59d47572-b9936849-3" '('('"scheme" (StructType '('"key" (DataType 'String)) '('"value" (StructType '('Avg1 (OptionalType $4)) '('Avg2 $4)))))))) (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 '( (let $18 (Uint64 '1)) (let $17 (IfPresent (Member $16 '"key") (lambda '($19) (Just '($19 $18))) (Nothing (OptionalType (TupleType (DataType 'Int64) (DataType 'Uint64)))))) (return (AsStruct '('Avg1 $17) '('Avg2 '((Member $16 '"sub") $18)))) ))) (lambda '($20 $21 $22) (block '( (let $23 (IfPresent (Member $21 '"key") (lambda '($28) (block '( (let $29 (Uint64 '1)) (return (Just '($28 $29))) ))) (Nothing (OptionalType (TupleType (DataType 'Int64) (DataType 'Uint64)))))) (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)) (let $25 (Member $22 'Avg2)) (return (AsStruct '('Avg1 $24) '('Avg2 '((+ (Nth $25 '0) (Member $21 '"sub")) (Inc (Nth $25 '1)))))) ))) (lambda '($30 $31) (Just (AsStruct '('"value" $31) '('"key" (String '""))))))) (return $6) ) )"; CompileAndDisassemble(program); } Y_UNIT_TEST(SelectCommonAncestor) { const auto program = R"( ( (let $1 (DataSink 'result)) (let $2 (DataSink '"yt" '"plato")) (let $3 '('"key" '"value")) (let $4 (DataSource '"yt" '"plato")) (let $5 (DataType 'String)) (let $6 (OptionalType $5)) (let $7 (MrTempTable $2 '"tmp/41c7eb81-87a9f8b6-70daa714-11" '('('"scheme" (StructType '('"key" $5) '('"value" (StructType '('Histogram0 $6) '('Histogram1 $6)))))))) (let $8 (Udf 'Histogram.AdaptiveWardHistogram_Create (Void) (VoidType) '"" (CallableType '() '((ResourceType '"Histogram.AdaptiveWard")) '((DataType 'Double)) '((DataType 'Double)) '((DataType 'Uint32))))) (let $9 (Double '1.0)) (let $10 (Cast (Int32 '"1") 'Uint32)) (let $11 (Double '1.0)) (let $12 (Cast (Int32 '"1000000") 'Uint32)) (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 '( (let $26 '((DataType 'Double))) (let $27 (CallableType '() '((ResourceType '"Histogram.AdaptiveWard")) $26 $26 '((DataType 'Uint32)))) (let $28 '((Unwrap (Cast (Member $24 '"key") 'Double)) $9 $10)) (return (Just (NamedApply $8 $28 (AsStruct) (Uint32 '"0")))) ))))) '('Histogram1 (FlatMap (Cast (Member $24 '"value") 'Double) (lambda '($29) (block '( (let $30 '((Unwrap (Cast (Member $24 '"value") 'Double)) $11 $12)) (return (Just (NamedApply $8 $30 (AsStruct) (Uint32 '"1")))) ))))))) (lambda '($31 $32 $33) (block '( (let $34 (Udf 'Histogram.AdaptiveWardHistogram_AddValue (Void) (VoidType) '"" (CallableType '() '((ResourceType '"Histogram.AdaptiveWard")) '((ResourceType '"Histogram.AdaptiveWard")) '((DataType 'Double)) '((DataType 'Double))))) (let $35 (Uint32 '"0")) (let $36 (IfPresent (Member $33 'Histogram0) (lambda '($39) (block '( (let $40 (Cast (Member $32 '"key") 'Double)) (let $41 '((ResourceType '"Histogram.AdaptiveWard"))) (let $42 '((DataType 'Double))) (let $43 (CallableType '() $41 $41 $42 $42)) (let $44 '($39 (Unwrap $40) $9)) (let $45 (NamedApply $34 $44 (AsStruct) $35)) (return (Just (If (Exists $40) $45 $39))) ))) (FlatMap (Cast (Member $32 '"key") 'Double) (lambda '($46) (block '( (let $47 '((Unwrap (Cast (Member $32 '"key") 'Double)) $9 $10)) (return (Just (NamedApply $8 $47 (AsStruct) $35))) )))))) (let $37 (Uint32 '"1")) (let $38 (IfPresent (Member $33 'Histogram1) (lambda '($48) (block '( (let $49 (Cast (Member $32 '"value") 'Double)) (let $50 '($48 (Unwrap $49) $11)) (let $51 (NamedApply $34 $50 (AsStruct) $37)) (return (Just (If (Exists $49) $51 $48))) ))) (FlatMap (Cast (Member $32 '"value") 'Double) (lambda '($52) (block '( (let $53 '((Unwrap (Cast (Member $32 '"value") 'Double)) $11 $12)) (return (Just (NamedApply $8 $53 (AsStruct) $37))) )))))) (return (AsStruct '('Histogram0 $36) '('Histogram1 $38))) ))) (lambda '($54 $55) (block '( (let $56 (lambda '($57) (block '( (let $58 (CallableType '() '((DataType 'String)) '((ResourceType '"Histogram.AdaptiveWard")))) (let $59 (Udf 'Histogram.AdaptiveWardHistogram_Serialize (Void) (VoidType) '"" $58)) (return (Just (Apply $59 $57))) )))) (return (Just (AsStruct '('"value" (AsStruct '('Histogram0 (FlatMap (Member $55 'Histogram0) $56)) '('Histogram1 (FlatMap (Member $55 'Histogram1) $56)))) '('"key" (String '""))))) ))))) (let $14 (DataType 'Double)) (let $15 (OptionalType (StructType '('"Bins" (ListType (StructType '('"Frequency" $14) '('"Position" $14)))) '('"Max" $14) '('"Min" $14) '('"WeightsSum" $14)))) (let $16 (MrTempTable $2 '"tmp/b6d6c3ee-30bb3e55-ea0c48bc-12" '('('"scheme" (StructType '('"key_histogram" $15) '('"value_histogram" $15)))))) (let $17 (MrReduce! $13 $2 $7 $3 '() $4 $16 '('('"reduceBy" '('"key"))) (lambda '($60 $61) (block '( (let $67 (Udf 'Histogram.AdaptiveWardHistogram_Deserialize (Void) (VoidType) '"" (CallableType '() '((ResourceType '"Histogram.AdaptiveWard")) '((DataType 'String)) '((DataType 'Uint32))))) (let $62 (lambda '($68) (block '( (let $69 (CallableType '() '((ResourceType '"Histogram.AdaptiveWard")) '((DataType 'String)) '((DataType 'Uint32)))) (return (Just (Apply $67 $68 $10))) )))) (let $63 (lambda '($70) (Just (Apply $67 $70 $12)))) (let $64 (Fold1 (FlatMap $61 (lambda '($65) (Just (Member $65 '"value")))) (lambda '($66) (block '( (return (AsStruct '('Histogram0 (FlatMap (Member $66 'Histogram0) $62)) '('Histogram1 (FlatMap (Member $66 'Histogram1) $63)))) ))) (lambda '($71 $72) (block '( (let $73 (lambda '($76 $77) (block '( (let $78 '((ResourceType '"Histogram.AdaptiveWard"))) (let $79 (CallableType '() $78 $78 $78)) (let $80 (Udf 'Histogram.AdaptiveWardHistogram_Merge (Void) (VoidType) '"" $79)) (return (Apply $80 $76 $77)) )))) (let $74 (OptionalReduce (FlatMap (Member $71 'Histogram0) $62) (Member $72 'Histogram0) $73)) (let $75 (OptionalReduce (FlatMap (Member $71 'Histogram1) $63) (Member $72 'Histogram1) $73)) (return (AsStruct '('Histogram0 $74) '('Histogram1 $75))) ))))) (return (FlatMap $64 (lambda '($81) (block '( (let $82 (lambda '($83) (block '( (let $84 (DataType 'Double)) (let $85 (CallableType '() '((StructType '('"Bins" (ListType (StructType '('"Frequency" $84) '('"Position" $84)))) '('"Max" $84) '('"Min" $84) '('"WeightsSum" $84))) '((ResourceType '"Histogram.AdaptiveWard")))) (let $86 (Udf 'Histogram.AdaptiveWardHistogram_GetResult (Void) (VoidType) '"" $85)) (return (Just (Apply $86 $83))) )))) (return (AsList (AsStruct '('"key_histogram" (FlatMap (Member $81 'Histogram0) $82)) '('"value_histogram" (FlatMap (Member $81 'Histogram1) $82))))) ))))) ))))) (let $18 '('"key_histogram" '"value_histogram")) (let $19 '('('type) '('autoref) '('columns $18))) (let $20 (ResPull! world $1 (Key) (Right! (MrReadTable! $17 $4 $16 $18 '())) $19 '"yt")) (return (Commit! (Commit! $20 $1) $2 '('('"epoch" '"1")))) ) )"; CompileAndDisassemble(program); } Y_UNIT_TEST(Parameters) { const auto program = R"( ( (let $nameType (OptionalType (DataType 'String))) (let $1 (Read! world (DataSource '"kikimr" '"local_ut") (Key '('table (String '"tmp/table"))) (Void) '())) (let $2 (DataSink 'result)) (let $5 (Write! (Left! $1) $2 (Key) (FlatMap (Filter (Right! $1) (lambda '($9) (Coalesce (And (== (Member $9 '"Group") (Parameter '"$Group" (DataType 'Uint32))) (== (Member $9 '"Name") (Parameter '"$Name" $nameType))) (Bool 'false)))) (lambda '($10) (AsList $10))) '('('type) '('autoref)))) (let $6 (Read! (Commit! $5 $2) (DataSource '"kikimr" '"local_ut") (Key '('table (String '"tmp/table"))) (Void) '())) (let $7 (DataSink 'result)) (let $8 (Write! (Left! $6) $7 (Key) (FlatMap (Filter (Right! $6) (lambda '($11) (Coalesce (And (== (Member $11 '"Group") (+ (Parameter '"$Group" (DataType 'Uint32)) (Int32 '"1"))) (== (Member $11 '"Name") (Coalesce (Parameter '"$Name" $nameType) (String '"Empty")))) (Bool 'false)))) (lambda '($12) (AsList $12))) '('('type) '('autoref)))) (return (Commit! $8 $7)) ) )"; const auto disassembled = CompileAndDisassemble(program); UNIT_ASSERT(TString::npos != disassembled.find("(declare $Group (DataType 'Uint32))")); UNIT_ASSERT(TString::npos != disassembled.find("(declare $Name (OptionalType (DataType 'String)))")); } Y_UNIT_TEST(ParametersDifferentTypes) { const auto program = R"( ( (let $1 (Read! world (DataSource '"kikimr" '"local_ut") (Key '('table (String '"tmp/table"))) (Void) '())) (let $2 (DataSink 'result)) (let $5 (Write! (Left! $1) $2 (Key) (FlatMap (Filter (Right! $1) (lambda '($9) (Coalesce (And (== (Member $9 '"Group") (Parameter '"$Group" (DataType 'Uint32))) (== (Member $9 '"Name") (Parameter '"$Name" (OptionalType (DataType 'String))))) (Bool 'false)))) (lambda '($10) (AsList $10))) '('('type) '('autoref)))) (let $6 (Read! (Commit! $5 $2) (DataSource '"kikimr" '"local_ut") (Key '('table (String '"tmp/table"))) (Void) '())) (let $7 (DataSink 'result)) (let $8 (Write! (Left! $6) $7 (Key) (FlatMap (Filter (Right! $6) (lambda '($11) (Coalesce (And (== (Member $11 '"Group") (+ (Parameter '"$Group" (DataType 'Uint32)) (Int32 '"1"))) (== (Member $11 '"Name") (Coalesce (Parameter '"$Name" (OptionalType (DataType 'Int32))) (String '"Empty")))) (Bool 'false)))) (lambda '($12) (AsList $12))) '('('type) '('autoref)))) (return (Commit! $8 $7)) ) )"; const auto disassembled = CompileAndDisassemble(program, false); UNIT_ASSERT(TString::npos != disassembled.find("(declare $Group (DataType 'Uint32))")); UNIT_ASSERT(TString::npos != disassembled.find("(declare $Name (OptionalType (DataType 'String)))")); } } } // namespace NYql