#include "yql_expr.h"
#include <library/cpp/testing/unittest/registar.h>
#include <util/string/hex.h>
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<ui32>()) {
const bool success = CompileExpr(root, exprRoot, exprCtx, nullptr, nullptr, typeAnnotationIndex != Max<ui32>(), typeAnnotationIndex);
exprCtx.IssueManager.GetIssues().PrintTo(Cout);
UNIT_ASSERT(success);
UNIT_ASSERT_VALUES_EQUAL(exprRoot->GetState(), typeAnnotationIndex != Max<ui32>() ? 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<TPosition, TPosition> *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