123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044 |
- #include "yql_expr.h"
- #include "yql_ast_annotation.h"
- #include "yql_gc_nodes.h"
- #include <yql/essentials/utils/utf8.h>
- #include <yql/essentials/utils/fetch/fetch.h>
- #include <yql/essentials/core/issue/yql_issue.h>
- #include <yql/essentials/parser/pg_catalog/catalog.h>
- #include <library/cpp/containers/stack_vector/stack_vec.h>
- #include <util/generic/hash.h>
- #include <util/generic/size_literals.h>
- #include <util/string/cast.h>
- #include <util/string/join.h>
- #include <util/digest/fnv.h>
- #include <util/digest/murmur.h>
- #include <util/digest/city.h>
- #include <util/digest/numeric.h>
- #include <util/string/cast.h>
- #include <openssl/sha.h>
- #include <map>
- #include <unordered_set>
- namespace NYql {
- const TStringBuf ZeroString = "";
- const char Dot = '.';
- const char Sep = '/';
- const TStringBuf PkgPrefix = "pkg";
- void ReportError(TExprContext& ctx, const TIssue& issue) {
- ctx.AddError(issue);
- }
- namespace {
- template <typename T>
- const T* FindType(const T& sample, TExprContext& ctx) {
- const auto it = ctx.TypeSet.find(&sample);
- return ctx.TypeSet.cend() != it ? static_cast<const T*>(*it) : nullptr;
- }
- template <typename T, typename... Args>
- const T* AddType(TExprContext& ctx, Args&&... args) {
- Y_DEBUG_ABORT_UNLESS(!ctx.Frozen);
- ctx.TypeNodes.emplace(new T(std::forward<Args>(args)...));
- const auto ins = ctx.TypeSet.emplace(ctx.TypeNodes.top().get());
- return static_cast<const T*>(*ins.first);
- }
- void DumpNode(const TExprNode& node, IOutputStream& out, ui32 level, TNodeSet& visited) {
- for (ui32 i = 0; i < level; ++i) {
- out.Write(' ');
- }
- out << "#" << node.UniqueId() << " [" << node.Type() << "]";
- if (node.Type() == TExprNode::Atom || node.Type() == TExprNode::Callable || node.Type() == TExprNode::Argument) {
- out << " <" << node.Content() << ">";
- }
- constexpr bool WithTypes = false;
- constexpr bool WithConstraints = false;
- constexpr bool WithScope = false;
- if constexpr (WithTypes) {
- if (node.GetTypeAnn()) {
- out << ", " << *node.GetTypeAnn();
- }
- }
- if constexpr (WithConstraints) {
- if (node.GetState() >= TExprNode::EState::ConstrComplete) {
- out << ", " << node.GetConstraintSet();
- }
- }
- if constexpr (WithScope) {
- if (const auto scope = node.GetDependencyScope()) {
- out << ", (";
- if (const auto outer = scope->first) {
- out << '#' << outer->UniqueId();
- } else {
- out << "null";
- }
- out << ',';
- if (const auto inner = scope->second) {
- out << '#' << inner->UniqueId();
- } else {
- out << "null";
- }
- out << ')';
- }
- }
- bool showChildren = true;
- if (!visited.emplace(&node).second) {
- if (node.Type() == TExprNode::Callable || node.Type() == TExprNode::List
- || node.Type() == TExprNode::Lambda || node.Type() == TExprNode::Arguments) {
- out << " ...";
- showChildren = false;
- }
- }
- out << "\n";
- if (showChildren) {
- for (auto& child : node.Children()) {
- DumpNode(*child, out, level + 1, visited);
- }
- }
- }
- struct TContext {
- struct TFrame {
- THashMap<TString, TExprNode::TListType> Bindings;
- THashMap<TString, TString> Imports;
- TExprNode::TListType Return;
- };
- TExprContext& Expr;
- TVector<TFrame> Frames;
- TLibraryCohesion Cohesion;
- std::unordered_set<TString> OverrideLibraries;
- TNodeOnNodeOwnedMap DeepClones;
- const TAnnotationNodeMap* Annotations = nullptr;
- IModuleResolver* ModuleResolver = nullptr;
- IUrlListerManager* UrlListerManager = nullptr;
- ui32 TypeAnnotationIndex = Max<ui32>();
- TString File;
- ui16 SyntaxVersion = 0;
- TContext(TExprContext& expr)
- : Expr(expr)
- {
- }
- void AddError(const TAstNode& node, const TString& message) {
- Expr.AddError(TIssue(node.GetPosition(), message));
- }
- void AddInfo(const TAstNode& node, const TString& message) {
- auto issue = TIssue(node.GetPosition(), message);
- issue.SetCode(TIssuesIds::INFO, TSeverityIds::S_INFO);
- Expr.AddError(issue);
- }
- TExprNode::TPtr&& ProcessNode(const TAstNode& node, TExprNode::TPtr&& exprNode) {
- if (TypeAnnotationIndex != Max<ui32>()) {
- exprNode->SetTypeAnn(CompileTypeAnnotation(node));
- }
- return std::move(exprNode);
- }
- void PushFrame() {
- Frames.push_back(TFrame());
- }
- void PopFrame() {
- Frames.pop_back();
- }
- TExprNode::TListType FindBinding(const TStringBuf& name) const {
- for (auto it = Frames.crbegin(); it != Frames.crend(); ++it) {
- const auto r = it->Bindings.find(name);
- if (it->Bindings.cend() != r)
- return r->second;
- }
- return {};
- }
- TString FindImport(const TStringBuf& name) const {
- for (auto it = Frames.crbegin(); it != Frames.crend(); ++it) {
- const auto r = it->Imports.find(name);
- if (it->Imports.cend() != r)
- return r->second;
- }
- return TString();
- }
- const TTypeAnnotationNode* CompileTypeAnnotation(const TAstNode& node) {
- auto ptr = Annotations->FindPtr(&node);
- if (!ptr || TypeAnnotationIndex >= ptr->size()) {
- AddError(node, "Failed to load type annotation");
- return nullptr;
- }
- return CompileTypeAnnotationNode(*(*ptr)[TypeAnnotationIndex]);
- }
- const TTypeAnnotationNode* CompileTypeAnnotationNode(const TAstNode& node) {
- if (node.IsAtom()) {
- if (node.GetContent() == TStringBuf(".")) {
- return nullptr;
- }
- else if (node.GetContent() == TStringBuf("Unit")) {
- return Expr.MakeType<TUnitExprType>();
- }
- else if (node.GetContent() == TStringBuf("World")) {
- return Expr.MakeType<TWorldExprType>();
- }
- else if (node.GetContent() == TStringBuf("Void")) {
- return Expr.MakeType<TVoidExprType>();
- }
- else if (node.GetContent() == TStringBuf("Null")) {
- return Expr.MakeType<TNullExprType>();
- }
- else if (node.GetContent() == TStringBuf("Generic")) {
- return Expr.MakeType<TGenericExprType>();
- }
- else if (node.GetContent() == TStringBuf("EmptyList")) {
- return Expr.MakeType<TEmptyListExprType>();
- }
- else if (node.GetContent() == TStringBuf("EmptyDict")) {
- return Expr.MakeType<TEmptyDictExprType>();
- }
- else {
- AddError(node, TStringBuilder() << "Unknown type annotation: " << node.GetContent());
- return nullptr;
- }
- } else {
- if (node.GetChildrenCount() == 0) {
- AddError(node, "Bad type annotation, expected not empty list");
- return nullptr;
- }
- if (!node.GetChild(0)->IsAtom()) {
- AddError(node, "Bad type annotation, first list item must be an atom");
- return nullptr;
- }
- auto content = node.GetChild(0)->GetContent();
- if (content == TStringBuf("Data")) {
- const auto count = node.GetChildrenCount();
- if (!(count == 2 || count == 4) || !node.GetChild(1)->IsAtom()) {
- AddError(node, "Bad data type annotation");
- return nullptr;
- }
- auto slot = NUdf::FindDataSlot(node.GetChild(1)->GetContent());
- if (!slot) {
- AddError(node, "Bad data type annotation");
- return nullptr;
- }
- if (count == 2) {
- return Expr.MakeType<TDataExprType>(*slot);
- } else {
- if (!(node.GetChild(2)->IsAtom() && node.GetChild(3)->IsAtom())) {
- AddError(node, "Bad data type annotation");
- return nullptr;
- }
- auto ann = Expr.MakeType<TDataExprParamsType>(*slot, node.GetChild(2)->GetContent(), node.GetChild(3)->GetContent());
- if (!ann->Validate(node.GetPosition(), Expr)) {
- return nullptr;
- }
- return ann;
- }
- } else if (content == TStringBuf("Pg")) {
- const auto count = node.GetChildrenCount();
- if (count != 2 || !node.GetChild(1)->IsAtom()) {
- AddError(node, "Bad data type annotation");
- return nullptr;
- }
- auto typeId = NPg::LookupType(TString(node.GetChild(1)->GetContent())).TypeId;
- return Expr.MakeType<TPgExprType>(typeId);
- } else if (content == TStringBuf("List")) {
- if (node.GetChildrenCount() != 2) {
- AddError(node, "Bad list type annotation");
- return nullptr;
- }
- auto r = CompileTypeAnnotationNode(*node.GetChild(1));
- if (!r)
- return nullptr;
- return Expr.MakeType<TListExprType>(r);
- } else if (content == TStringBuf("Stream")) {
- if (node.GetChildrenCount() != 2) {
- AddError(node, "Bad stream type annotation");
- return nullptr;
- }
- auto r = CompileTypeAnnotationNode(*node.GetChild(1));
- if (!r)
- return nullptr;
- return Expr.MakeType<TStreamExprType>(r);
- } else if (content == TStringBuf("Struct")) {
- TVector<const TItemExprType*> children;
- for (size_t index = 1; index < node.GetChildrenCount(); ++index) {
- auto r = CompileTypeAnnotationNode(*node.GetChild(index));
- if (!r)
- return nullptr;
- if (r->GetKind() != ETypeAnnotationKind::Item) {
- AddError(node, "Expected item type annotation");
- return nullptr;
- }
- children.push_back(r->Cast<TItemExprType>());
- }
- auto ann = Expr.MakeType<TStructExprType>(children);
- if (!ann->Validate(node.GetPosition(), Expr)) {
- return nullptr;
- }
- return ann;
- } else if (content == TStringBuf("Multi")) {
- TTypeAnnotationNode::TListType children;
- for (size_t index = 1; index < node.GetChildrenCount(); ++index) {
- auto r = CompileTypeAnnotationNode(*node.GetChild(index));
- if (!r)
- return nullptr;
- children.push_back(r);
- }
- auto ann = Expr.MakeType<TMultiExprType>(children);
- if (!ann->Validate(node.GetPosition(), Expr)) {
- return nullptr;
- }
- return ann;
- } else if (content == TStringBuf("Tuple")) {
- TTypeAnnotationNode::TListType children;
- for (size_t index = 1; index < node.GetChildrenCount(); ++index) {
- auto r = CompileTypeAnnotationNode(*node.GetChild(index));
- if (!r)
- return nullptr;
- children.push_back(r);
- }
- auto ann = Expr.MakeType<TTupleExprType>(children);
- if (!ann->Validate(node.GetPosition(), Expr)) {
- return nullptr;
- }
- return ann;
- } else if (content == TStringBuf("Item")) {
- if (node.GetChildrenCount() != 3 || !node.GetChild(1)->IsAtom()) {
- AddError(node, "Bad item type annotation");
- return nullptr;
- }
- auto r = CompileTypeAnnotationNode(*node.GetChild(2));
- if (!r)
- return nullptr;
- return Expr.MakeType<TItemExprType>(TString(node.GetChild(1)->GetContent()), r);
- } else if (content == TStringBuf("Optional")) {
- if (node.GetChildrenCount() != 2) {
- AddError(node, "Bad optional type annotation");
- return nullptr;
- }
- auto r = CompileTypeAnnotationNode(*node.GetChild(1));
- if (!r)
- return nullptr;
- return Expr.MakeType<TOptionalExprType>(r);
- } else if (content == TStringBuf("Type")) {
- if (node.GetChildrenCount() != 2) {
- AddError(node, "Bad type annotation");
- return nullptr;
- }
- auto r = CompileTypeAnnotationNode(*node.GetChild(1));
- if (!r)
- return nullptr;
- return Expr.MakeType<TTypeExprType>(r);
- }
- else if (content == TStringBuf("Dict")) {
- if (node.GetChildrenCount() != 3) {
- AddError(node, "Bad dict annotation");
- return nullptr;
- }
- auto r1 = CompileTypeAnnotationNode(*node.GetChild(1));
- if (!r1)
- return nullptr;
- auto r2 = CompileTypeAnnotationNode(*node.GetChild(2));
- if (!r2)
- return nullptr;
- auto ann = Expr.MakeType<TDictExprType>(r1, r2);
- if (!ann->Validate(node.GetPosition(), Expr)) {
- return nullptr;
- }
- return ann;
- }
- else if (content == TStringBuf("Callable")) {
- if (node.GetChildrenCount() <= 2) {
- AddError(node, "Bad callable annotation");
- return nullptr;
- }
- TVector<TCallableExprType::TArgumentInfo> args;
- size_t optCount = 0;
- TString payload;
- if (!node.GetChild(1)->IsList()) {
- AddError(node, "Bad callable annotation - expected list");
- return nullptr;
- }
- if (node.GetChild(1)->GetChildrenCount() > 2) {
- AddError(node, "Bad callable annotation - too many settings nodes");
- return nullptr;
- }
- if (node.GetChild(1)->GetChildrenCount() > 0) {
- auto optChild = node.GetChild(1)->GetChild(0);
- if (!optChild->IsAtom()) {
- AddError(node, "Bad callable annotation - expected atom");
- return nullptr;
- }
- if (!TryFromString(optChild->GetContent(), optCount)) {
- AddError(node, TStringBuilder() << "Bad callable optional args count: " << node.GetChild(1)->GetContent());
- return nullptr;
- }
- }
- if (node.GetChild(1)->GetChildrenCount() > 1) {
- auto payloadChild = node.GetChild(1)->GetChild(1);
- if (!payloadChild->IsAtom()) {
- AddError(node, "Bad callable annotation - expected atom");
- return nullptr;
- }
- payload = payloadChild->GetContent();
- }
- auto retSettings = node.GetChild(2);
- if (!retSettings->IsList() || retSettings->GetChildrenCount() != 1) {
- AddError(node, "Bad callable annotation - expected list of size 1");
- return nullptr;
- }
- auto retType = CompileTypeAnnotationNode(*retSettings->GetChild(0));
- if (!retType)
- return nullptr;
- for (size_t index = 3; index < node.GetChildrenCount(); ++index) {
- auto argSettings = node.GetChild(index);
- if (!argSettings->IsList() || argSettings->GetChildrenCount() < 1 ||
- argSettings->GetChildrenCount() > 3) {
- AddError(node, "Bad callable annotation - expected list of size 1..3");
- return nullptr;
- }
- auto r = CompileTypeAnnotationNode(*argSettings->GetChild(0));
- if (!r)
- return nullptr;
- TCallableExprType::TArgumentInfo arg;
- arg.Type = r;
- if (argSettings->GetChildrenCount() > 1) {
- auto nameChild = argSettings->GetChild(1);
- if (!nameChild->IsAtom()) {
- AddError(node, "Bad callable annotation - expected atom");
- return nullptr;
- }
- arg.Name = nameChild->GetContent();
- }
- if (argSettings->GetChildrenCount() > 2) {
- auto flagsChild = argSettings->GetChild(2);
- if (!flagsChild->IsAtom()) {
- AddError(node, "Bad callable annotation - expected atom");
- return nullptr;
- }
- if (!TryFromString(flagsChild->GetContent(), arg.Flags)) {
- AddError(node, "Bad callable annotation - bad integer");
- return nullptr;
- }
- }
- args.push_back(arg);
- }
- auto ann = Expr.MakeType<TCallableExprType>(retType, args, optCount, payload);
- if (!ann->Validate(node.GetPosition(), Expr)) {
- return nullptr;
- }
- return ann;
- } else if (content == TStringBuf("Resource")) {
- if (node.GetChildrenCount() != 2 || !node.GetChild(1)->IsAtom()) {
- AddError(node, "Bad resource type annotation");
- return nullptr;
- }
- return Expr.MakeType<TResourceExprType>(TString(node.GetChild(1)->GetContent()));
- } else if (content == TStringBuf("Tagged")) {
- if (node.GetChildrenCount() != 3 || !node.GetChild(2)->IsAtom()) {
- AddError(node, "Bad tagged type annotation");
- return nullptr;
- }
- auto type = CompileTypeAnnotationNode(*node.GetChild(1));
- if (!type)
- return nullptr;
- TString tag(node.GetChild(2)->GetContent());
- auto ann = Expr.MakeType<TTaggedExprType>(type, tag);
- if (!ann->Validate(node.GetPosition(), Expr)) {
- return nullptr;
- }
- return ann;
- } else if (content == TStringBuf("Error")) {
- if (node.GetChildrenCount() != 5 || !node.GetChild(1)->IsAtom() ||
- !node.GetChild(2)->IsAtom() || !node.GetChild(3)->IsAtom() || !node.GetChild(4)->IsAtom()) {
- AddError(node, "Bad error type annotation");
- return nullptr;
- }
- ui32 row;
- if (!TryFromString(node.GetChild(1)->GetContent(), row)) {
- AddError(node, TStringBuilder() << "Bad integer: " << node.GetChild(1)->GetContent());
- return nullptr;
- }
- ui32 column;
- if (!TryFromString(node.GetChild(2)->GetContent(), column)) {
- AddError(node, TStringBuilder() << "Bad integer: " << node.GetChild(2)->GetContent());
- return nullptr;
- }
- auto file = TString(node.GetChild(3)->GetContent());
- return Expr.MakeType<TErrorExprType>(TIssue(TPosition(column, row, file), TString(node.GetChild(4)->GetContent())));
- } else if (content == TStringBuf("Variant")) {
- if (node.GetChildrenCount() != 2) {
- AddError(node, "Bad variant type annotation");
- return nullptr;
- }
- auto r = CompileTypeAnnotationNode(*node.GetChild(1));
- if (!r)
- return nullptr;
- auto ann = Expr.MakeType<TVariantExprType>(r);
- if (!ann->Validate(node.GetPosition(), Expr)) {
- return nullptr;
- }
- return ann;
- } else if (content == TStringBuf("Stream")) {
- if (node.GetChildrenCount() != 2) {
- AddError(node, "Bad stream type annotation");
- return nullptr;
- }
- auto r = CompileTypeAnnotationNode(*node.GetChild(1));
- if (!r)
- return nullptr;
- return Expr.MakeType<TStreamExprType>(r);
- } else if (content == TStringBuf("Flow")) {
- if (node.GetChildrenCount() != 2) {
- AddError(node, "Bad flow type annotation");
- return nullptr;
- }
- auto r = CompileTypeAnnotationNode(*node.GetChild(1));
- if (!r)
- return nullptr;
- return Expr.MakeType<TFlowExprType>(r);
- } else if (content == TStringBuf("Block")) {
- if (node.GetChildrenCount() != 2) {
- AddError(node, "Bad block type annotation");
- return nullptr;
- }
- auto r = CompileTypeAnnotationNode(*node.GetChild(1));
- if (!r)
- return nullptr;
- return Expr.MakeType<TBlockExprType>(r);
- } else if (content == TStringBuf("Scalar")) {
- if (node.GetChildrenCount() != 2) {
- AddError(node, "Bad scalar type annotation");
- return nullptr;
- }
- auto r = CompileTypeAnnotationNode(*node.GetChild(1));
- if (!r)
- return nullptr;
- return Expr.MakeType<TScalarExprType>(r);
- } else {
- AddError(node, TStringBuilder() << "Unknown type annotation");
- return nullptr;
- }
- }
- }
- };
- TAstNode* ConvertTypeAnnotationToAst(const TTypeAnnotationNode& annotation, TMemoryPool& pool, bool refAtoms) {
- switch (annotation.GetKind()) {
- case ETypeAnnotationKind::Unit:
- {
- return TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Unit"), pool);
- }
- case ETypeAnnotationKind::Tuple:
- {
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Tuple"), pool);
- TSmallVec<TAstNode*> children;
- children.push_back(self);
- for (auto& child : annotation.Cast<TTupleExprType>()->GetItems()) {
- children.push_back(ConvertTypeAnnotationToAst(*child, pool, refAtoms));
- }
- return TAstNode::NewList(TPosition(), children.data(), children.size(), pool);
- }
- case ETypeAnnotationKind::Struct:
- {
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Struct"), pool);
- TSmallVec<TAstNode*> children;
- children.push_back(self);
- for (auto& child : annotation.Cast<TStructExprType>()->GetItems()) {
- children.push_back(ConvertTypeAnnotationToAst(*child, pool, refAtoms));
- }
- return TAstNode::NewList(TPosition(), children.data(), children.size(), pool);
- }
- case ETypeAnnotationKind::List:
- {
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("List"), pool);
- auto itemType = ConvertTypeAnnotationToAst(*annotation.Cast<TListExprType>()->GetItemType(), pool, refAtoms);
- return TAstNode::NewList(TPosition(), pool, self, itemType);
- }
- case ETypeAnnotationKind::Optional:
- {
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Optional"), pool);
- auto itemType = ConvertTypeAnnotationToAst(*annotation.Cast<TOptionalExprType>()->GetItemType(), pool, refAtoms);
- return TAstNode::NewList(TPosition(), pool, self, itemType);
- }
- case ETypeAnnotationKind::Item:
- {
- auto casted = annotation.Cast<TItemExprType>();
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Item"), pool);
- auto name = refAtoms ?
- TAstNode::NewLiteralAtom(TPosition(), casted->GetName(), pool, TNodeFlags::ArbitraryContent) :
- TAstNode::NewAtom(TPosition(), casted->GetName(), pool, TNodeFlags::ArbitraryContent);
- auto itemType = ConvertTypeAnnotationToAst(*casted->GetItemType(), pool, refAtoms);
- return TAstNode::NewList(TPosition(), pool, self, name, itemType);
- }
- case ETypeAnnotationKind::Data:
- {
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Data"), pool);
- auto datatype = refAtoms ?
- TAstNode::NewLiteralAtom(TPosition(), annotation.Cast<TDataExprType>()->GetName(), pool) :
- TAstNode::NewAtom(TPosition(), annotation.Cast<TDataExprType>()->GetName(), pool);
- if (auto params = dynamic_cast<const TDataExprParamsType*>(&annotation)) {
- auto param1 = refAtoms ?
- TAstNode::NewLiteralAtom(TPosition(), params->GetParamOne(), pool) :
- TAstNode::NewAtom(TPosition(), params->GetParamOne(), pool);
- auto param2 = refAtoms ?
- TAstNode::NewLiteralAtom(TPosition(), params->GetParamTwo(), pool) :
- TAstNode::NewAtom(TPosition(), params->GetParamTwo(), pool);
- return TAstNode::NewList(TPosition(), pool, self, datatype, param1, param2);
- }
- return TAstNode::NewList(TPosition(), pool, self, datatype);
- }
- case ETypeAnnotationKind::Pg:
- {
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Pg"), pool);
- auto name = TAstNode::NewLiteralAtom(TPosition(), annotation.Cast<TPgExprType>()->GetName(), pool);
- return TAstNode::NewList(TPosition(), pool, self, name);
- }
- case ETypeAnnotationKind::World:
- {
- return TAstNode::NewLiteralAtom(TPosition(), TStringBuf("World"), pool);
- }
- case ETypeAnnotationKind::Type:
- {
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Type"), pool);
- auto type = ConvertTypeAnnotationToAst(*annotation.Cast<TTypeExprType>()->GetType(), pool, refAtoms);
- return TAstNode::NewList(TPosition(), pool, self, type);
- }
- case ETypeAnnotationKind::Dict:
- {
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Dict"), pool);
- auto dictType = annotation.Cast<TDictExprType>();
- auto keyType = ConvertTypeAnnotationToAst(*dictType->GetKeyType(), pool, refAtoms);
- auto payloadType = ConvertTypeAnnotationToAst(*dictType->GetPayloadType(), pool, refAtoms);
- return TAstNode::NewList(TPosition(), pool, self, keyType, payloadType);
- }
- case ETypeAnnotationKind::Void:
- {
- return TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Void"), pool);
- }
- case ETypeAnnotationKind::Null:
- {
- return TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Null"), pool);
- }
- case ETypeAnnotationKind::Callable:
- {
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Callable"), pool);
- auto callable = annotation.Cast<TCallableExprType>();
- TSmallVec<TAstNode*> mainSettings;
- if (callable->GetOptionalArgumentsCount() > 0 || !callable->GetPayload().empty()) {
- auto optArgs = TAstNode::NewAtom(TPosition(), ToString(callable->GetOptionalArgumentsCount()), pool);
- mainSettings.push_back(optArgs);
- }
- if (!callable->GetPayload().empty()) {
- auto payload = TAstNode::NewAtom(TPosition(), callable->GetPayload(), pool, TNodeFlags::ArbitraryContent);
- mainSettings.push_back(payload);
- }
- TSmallVec<TAstNode*> children;
- children.push_back(self);
- children.push_back(TAstNode::NewList(TPosition(), mainSettings.data(), mainSettings.size(), pool));
- TSmallVec<TAstNode*> retSettings;
- retSettings.push_back(ConvertTypeAnnotationToAst(*callable->GetReturnType(), pool, refAtoms));
- children.push_back(TAstNode::NewList(TPosition(), retSettings.data(), retSettings.size(), pool));
- for (auto& arg : callable->GetArguments()) {
- TSmallVec<TAstNode*> argSettings;
- argSettings.push_back(ConvertTypeAnnotationToAst(*arg.Type, pool, refAtoms));
- if (!arg.Name.empty() || arg.Flags != 0) {
- auto name = TAstNode::NewAtom(TPosition(), arg.Name, pool, TNodeFlags::ArbitraryContent);
- argSettings.push_back(name);
- }
- if (arg.Flags != 0) {
- auto flags = TAstNode::NewAtom(TPosition(), ToString(arg.Flags), pool, TNodeFlags::ArbitraryContent);
- argSettings.push_back(flags);
- }
- children.push_back(TAstNode::NewList(TPosition(), argSettings.data(), argSettings.size(), pool));
- }
- return TAstNode::NewList(TPosition(), children.data(), children.size(), pool);
- }
- case ETypeAnnotationKind::Generic:
- {
- return TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Generic"), pool);
- }
- case ETypeAnnotationKind::Resource:
- {
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Resource"), pool);
- auto restype = refAtoms ?
- TAstNode::NewLiteralAtom(TPosition(), annotation.Cast<TResourceExprType>()->GetTag(), pool, TNodeFlags::ArbitraryContent) :
- TAstNode::NewAtom(TPosition(), annotation.Cast<TResourceExprType>()->GetTag(), pool, TNodeFlags::ArbitraryContent);
- return TAstNode::NewList(TPosition(), pool, self, restype);
- }
- case ETypeAnnotationKind::Tagged:
- {
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Tagged"), pool);
- auto type = ConvertTypeAnnotationToAst(*annotation.Cast<TTaggedExprType>()->GetBaseType(), pool, refAtoms);
- auto restype = refAtoms ?
- TAstNode::NewLiteralAtom(TPosition(), annotation.Cast<TTaggedExprType>()->GetTag(), pool, TNodeFlags::ArbitraryContent) :
- TAstNode::NewAtom(TPosition(), annotation.Cast<TTaggedExprType>()->GetTag(), pool, TNodeFlags::ArbitraryContent);
- return TAstNode::NewList(TPosition(), pool, self, type, restype);
- }
- case ETypeAnnotationKind::Error:
- {
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Error"), pool);
- const auto& err = annotation.Cast<TErrorExprType>()->GetError();
- auto row = TAstNode::NewAtom(TPosition(), ToString(err.Position.Row), pool);
- auto column = TAstNode::NewAtom(TPosition(), ToString(err.Position.Column), pool);
- auto file = refAtoms ?
- TAstNode::NewLiteralAtom(TPosition(), err.Position.File, pool, TNodeFlags::ArbitraryContent) :
- TAstNode::NewAtom(TPosition(), err.Position.File, pool, TNodeFlags::ArbitraryContent);
- auto message = refAtoms ?
- TAstNode::NewLiteralAtom(TPosition(), err.GetMessage(), pool, TNodeFlags::ArbitraryContent) :
- TAstNode::NewAtom(TPosition(), err.GetMessage(), pool, TNodeFlags::ArbitraryContent);
- return TAstNode::NewList(TPosition(), pool, self, row, column, file, message);
- }
- case ETypeAnnotationKind::Variant:
- {
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Variant"), pool);
- auto underlyingType = ConvertTypeAnnotationToAst(*annotation.Cast<TVariantExprType>()->GetUnderlyingType(), pool, refAtoms);
- return TAstNode::NewList(TPosition(), pool, self, underlyingType);
- }
- case ETypeAnnotationKind::Stream:
- {
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Stream"), pool);
- auto itemType = ConvertTypeAnnotationToAst(*annotation.Cast<TStreamExprType>()->GetItemType(), pool, refAtoms);
- return TAstNode::NewList(TPosition(), pool, self, itemType);
- }
- case ETypeAnnotationKind::Flow:
- {
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Flow"), pool);
- auto itemType = ConvertTypeAnnotationToAst(*annotation.Cast<TFlowExprType>()->GetItemType(), pool, refAtoms);
- return TAstNode::NewList(TPosition(), pool, self, itemType);
- }
- case ETypeAnnotationKind::Multi:
- {
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Multi"), pool);
- TSmallVec<TAstNode*> children;
- children.push_back(self);
- for (auto& child : annotation.Cast<TMultiExprType>()->GetItems()) {
- children.push_back(ConvertTypeAnnotationToAst(*child, pool, refAtoms));
- }
- return TAstNode::NewList(TPosition(), children.data(), children.size(), pool);
- }
- case ETypeAnnotationKind::EmptyList:
- {
- return TAstNode::NewLiteralAtom(TPosition(), TStringBuf("EmptyList"), pool);
- }
- case ETypeAnnotationKind::EmptyDict:
- {
- return TAstNode::NewLiteralAtom(TPosition(), TStringBuf("EmptyDict"), pool);
- }
- case ETypeAnnotationKind::Block:
- {
- auto type = annotation.Cast<TBlockExprType>();
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Block"), pool);
- auto itemType = ConvertTypeAnnotationToAst(*type->GetItemType(), pool, refAtoms);
- return TAstNode::NewList(TPosition(), pool, self, itemType);
- }
- case ETypeAnnotationKind::Scalar:
- {
- auto type = annotation.Cast<TScalarExprType>();
- auto self = TAstNode::NewLiteralAtom(TPosition(), TStringBuf("Scalar"), pool);
- auto itemType = ConvertTypeAnnotationToAst(*type->GetItemType(), pool, refAtoms);
- return TAstNode::NewList(TPosition(), pool, self, itemType);
- }
- case ETypeAnnotationKind::LastType:
- YQL_ENSURE(false, "Unknown kind: " << annotation.GetKind());
- }
- }
- TAstNode* AnnotateAstNode(TAstNode* node, const TExprNode* exprNode, ui32 flags, TMemoryPool& pool, bool refAtoms) {
- if (!flags)
- return node;
- TSmallVec<TAstNode*> children;
- if (flags & TExprAnnotationFlags::Position) {
- children.push_back(PositionAsNode(node->GetPosition(), pool));
- }
- if ((flags & TExprAnnotationFlags::Types)) {
- TAstNode* typeAnn = nullptr;
- if (exprNode) {
- YQL_ENSURE(exprNode->GetTypeAnn());
- typeAnn = ConvertTypeAnnotationToAst(*exprNode->GetTypeAnn(), pool, refAtoms);
- } else {
- typeAnn = TAstNode::NewLiteralAtom(node->GetPosition(), TStringBuf("."), pool);
- }
- children.push_back(typeAnn);
- }
- children.push_back(node);
- return TAstNode::NewList(node->GetPosition(), children.data(), children.size(), pool);
- }
- bool AddParameterDependencies(const TString& url, const TAstNode& node, TContext& ctx) {
- auto world = ctx.FindBinding("world");
- if (!world.empty()) {
- TSet<TString> names;
- SubstParameters(url, Nothing(), &names);
- for (const auto& name : names) {
- auto nameRef = ctx.FindBinding(name);
- if (nameRef.empty()) {
- ctx.AddError(node, TStringBuilder() << "Name not found: " << name);
- return false;
- }
- TExprNode::TListType args = world;
- args.insert(args.end(), nameRef.begin(), nameRef.end());
- auto newWorld = TExprNode::TListType{ ctx.Expr.NewCallable(node.GetPosition(), "Left!", {
- ctx.Expr.NewCallable(node.GetPosition(), "Cons!", std::move(args)) })};
- ctx.Frames.back().Bindings["world"] = newWorld;
- world = newWorld;
- }
- }
- return true;
- }
- TExprNode::TListType Compile(const TAstNode& node, TContext& ctx);
- TExprNode::TPtr CompileQuote(const TAstNode& node, TContext& ctx) {
- if (node.IsAtom()) {
- return ctx.ProcessNode(node, ctx.Expr.NewAtom(node.GetPosition(), TString(node.GetContent()), node.GetFlags()));
- } else {
- TExprNode::TListType children;
- children.reserve(node.GetChildrenCount());
- for (ui32 index = 0; index < node.GetChildrenCount(); ++index) {
- auto r = Compile(*node.GetChild(index), ctx);
- if (r.empty())
- return {};
- std::move(r.begin(), r.end(), std::back_inserter(children));
- }
- return ctx.ProcessNode(node, ctx.Expr.NewList(node.GetPosition(), std::move(children)));
- }
- }
- TExprNode::TListType CompileLambda(const TAstNode& node, TContext& ctx) {
- if (node.GetChildrenCount() < 2) {
- ctx.AddError(node, "Expected size of list at least 3.");
- return {};
- }
- const auto args = node.GetChild(1);
- if (!args->IsList() || args->GetChildrenCount() != 2 || !args->GetChild(0)->IsAtom() ||
- args->GetChild(0)->GetContent() != TStringBuf("quote") || !args->GetChild(1)->IsList()) {
- ctx.AddError(node, "Lambda arguments must be a quoted list of atoms");
- return {};
- }
- const auto params = args->GetChild(1);
- for (ui32 index = 0; index < params->GetChildrenCount(); ++index) {
- if (!params->GetChild(index)->IsAtom()) {
- ctx.AddError(node, "Lambda arguments must be a quoted list of atoms");
- return {};
- }
- }
- ctx.PushFrame();
- TExprNode::TListType argNodes;
- for (ui32 index = 0; index < params->GetChildrenCount(); ++index) {
- auto arg = params->GetChild(index);
- auto lambdaArg = ctx.ProcessNode(*arg, ctx.Expr.NewArgument(arg->GetPosition(), TString(arg->GetContent())));
- argNodes.push_back(lambdaArg);
- auto& binding = ctx.Frames.back().Bindings[arg->GetContent()];
- if (!binding.empty()) {
- ctx.PopFrame();
- ctx.AddError(*arg, TStringBuilder() << "Duplicated name of lambda parameter: " << arg->GetContent());
- return {};
- }
- binding = {lambdaArg};
- }
- TExprNode::TListType body;
- body.reserve(node.GetChildrenCount() - 2U);
- for (auto i = 2U; i < node.GetChildrenCount(); ++i) {
- auto r = Compile(*node.GetChild(i), ctx);
- if (r.empty())
- return {};
- std::move(r.begin(), r.end(), std::back_inserter(body));
- }
- ctx.PopFrame();
- auto arguments = ctx.ProcessNode(*args, ctx.Expr.NewArguments(args->GetPosition(), std::move(argNodes)));
- auto lambda = ctx.ProcessNode(node, ctx.Expr.NewLambda(node.GetPosition(), std::move(arguments), std::move(body)));
- return {lambda};
- }
- bool CompileSetPackageVersion(const TAstNode& node, TContext& ctx) {
- if (node.GetChildrenCount() != 3) {
- ctx.AddError(node, "Expected list of size 3");
- return false;
- }
- const auto name = node.GetChild(1);
- if (name->IsAtom() || name->GetChildrenCount() != 2 || !name->GetChild(0)->IsAtom() || !name->GetChild(1)->IsAtom() ||
- name->GetChild(0)->GetContent() != TStringBuf("quote")) {
- ctx.AddError(*name, "Expected quoted atom for package name");
- return false;
- }
- const auto versionNode = node.GetChild(2);
- if (versionNode->IsAtom() || versionNode->GetChildrenCount() != 2 || !versionNode->GetChild(0)->IsAtom() || !versionNode->GetChild(1)->IsAtom() ||
- versionNode->GetChild(0)->GetContent() != TStringBuf("quote")) {
- ctx.AddError(*versionNode, "Expected quoted atom for package version");
- return false;
- }
- ui32 version = 0;
- if (!versionNode->GetChild(1)->IsAtom() || !TryFromString(versionNode->GetChild(1)->GetContent(), version)) {
- ctx.AddError(*versionNode, TString("Expected package version as number, bad content ") + versionNode->GetChild(1)->GetContent());
- return false;
- }
- if (ctx.ModuleResolver && !ctx.ModuleResolver->SetPackageDefaultVersion(TString(name->GetChild(1)->GetContent()), version)) {
- ctx.AddError(*versionNode, TStringBuilder() << "Unable to specify version " << version << " for package " << name->GetChild(1)->GetContent());
- return false;
- }
- return true;
- }
- TExprNode::TPtr CompileBind(const TAstNode& node, TContext& ctx) {
- if (node.GetChildrenCount() != 3) {
- ctx.AddError(node, "Expected list of size 3");
- return nullptr;
- }
- const auto name = node.GetChild(1);
- if (!name->IsAtom()) {
- ctx.AddError(*name, "Expected atom");
- return nullptr;
- }
- const auto alias = node.GetChild(2);
- if (alias->IsAtom() || alias->GetChildrenCount() != 2 || !alias->GetChild(0)->IsAtom() || !alias->GetChild(1)->IsAtom() ||
- alias->GetChild(0)->GetContent() != TStringBuf("quote")) {
- ctx.AddError(*alias, "Expected quoted pair");
- return nullptr;
- }
- const auto& aliasValue = alias->GetChild(1)->GetContent();
- const auto& moduleName = name->GetContent();
- TStringBuilder baseMsg;
- baseMsg << "Module '" << name->GetContent() << "'";
- const auto& import = ctx.FindImport(moduleName);
- if (import.empty()) {
- ctx.AddError(*name, baseMsg << " does not exist");
- return nullptr;
- }
- if (ctx.ModuleResolver) {
- auto exportsPtr = ctx.ModuleResolver->GetModule(import);
- if (!exportsPtr) {
- ctx.AddError(*name, baseMsg << "'" << import << "' does not exist");
- return nullptr;
- }
- const auto& exports = exportsPtr->Symbols();
- const auto ex = exports.find(aliasValue);
- if (exports.cend() == ex) {
- ctx.AddError(*alias, baseMsg << " export '" << aliasValue << "' does not exist");
- return nullptr;
- }
- return ctx.Expr.DeepCopy(*ex->second, exportsPtr->ExprCtx(), ctx.DeepClones, true, false);
- } else {
- const auto stub = ctx.Expr.NewAtom(node.GetPosition(), "stub");
- ctx.Frames.back().Bindings[name->GetContent()] = {stub};
- ctx.Cohesion.Imports[stub.Get()] = std::make_pair(import, TString(aliasValue));
- return stub;
- }
- }
- bool CompileLet(const TAstNode& node, TContext& ctx) {
- if (node.GetChildrenCount() < 3) {
- ctx.AddError(node, "Expected size of list at least 3.");
- return false;
- }
- const auto name = node.GetChild(1);
- if (!name->IsAtom()) {
- ctx.AddError(*name, "Expected atom");
- return false;
- }
- TExprNode::TListType bind;
- bind.reserve(node.GetChildrenCount() - 2U);
- for (auto i = 2U; i < node.GetChildrenCount(); ++i) {
- auto r = Compile(*node.GetChild(i), ctx);
- if (r.empty())
- return false;
- std::move(r.begin(), r.end(), std::back_inserter(bind));
- }
- ctx.Frames.back().Bindings[name->GetContent()] = std::move(bind);
- return true;
- }
- bool CompileImport(const TAstNode& node, TContext& ctx) {
- if (node.GetChildrenCount() != 3) {
- ctx.AddError(node, "Expected list of size 3");
- return false;
- }
- const auto name = node.GetChild(1);
- if (!name->IsAtom()) {
- ctx.AddError(*name, "Expected atom");
- return false;
- }
- const auto alias = node.GetChild(2);
- if (!alias->IsListOfSize(2) || !alias->GetChild(0)->IsAtom() || !alias->GetChild(1)->IsAtom() ||
- alias->GetChild(0)->GetContent() != TStringBuf("quote")) {
- ctx.AddError(node, "Expected quoted pair");
- return false;
- }
- ctx.Frames.back().Imports[name->GetContent()] = alias->GetChild(1)->GetContent();
- return true;
- }
- bool CompileExport(const TAstNode& node, TContext& ctx) {
- if (node.GetChildrenCount() != 2) {
- ctx.AddError(node, "Expected list of size 2");
- return false;
- }
- const auto name = node.GetChild(1);
- if (!name->IsAtom()) {
- ctx.AddError(*name, "Expected atom");
- return false;
- }
- auto r = Compile(*node.GetChild(1), ctx);
- if (r.size() != 1U)
- return false;
- ctx.Cohesion.Exports.Symbols(ctx.Expr)[name->GetContent()] = std::move(r.front());
- return true;
- }
- bool CompileDeclare(const TAstNode& node, TContext& ctx, bool checkOnly) {
- if (node.GetChildrenCount() != 3) {
- ctx.AddError(node, "Expected list of size 3");
- return false;
- }
- const auto name = node.GetChild(1);
- if (!name->IsAtom()) {
- ctx.AddError(*name, "Expected atom");
- return false;
- }
- TString nameStr = TString(name->GetContent());
- if (nameStr.size() < 2) {
- ctx.AddError(*name, "Parameter name should be at least 2 characters long.");
- return false;
- }
- if (nameStr[0] == '$' && std::isdigit(nameStr[1])) {
- ctx.AddError(*name, "Parameter name cannot start with digit.");
- return false;
- }
- auto typeExpr = Compile(*node.GetChild(2), ctx);
- if (typeExpr.size() != 1U)
- return false;
- auto typePos = node.GetChild(2)->GetPosition();
- auto parameterExpr = ctx.ProcessNode(node,
- ctx.Expr.NewCallable(typePos, "Parameter", {
- ctx.Expr.NewAtom(node.GetPosition(), nameStr),
- std::move(typeExpr.front())
- }));
- bool error = false;
- if (checkOnly) {
- auto it = ctx.Frames.back().Bindings.find(nameStr);
- if (it == ctx.Frames.back().Bindings.end()) {
- ctx.AddError(*name, TStringBuilder() << "Missing parameter: " << nameStr);
- return false;
- }
- if (it->second.size() != 1 || !it->second.front()->IsCallable("Parameter")) {
- error = true;
- }
- } else {
- if (!ctx.Frames.back().Bindings.emplace(nameStr, TExprNode::TListType{ std::move(parameterExpr) }).second) {
- error = true;
- }
- }
- if (error) {
- ctx.AddError(node, TStringBuilder() << "Declare statement hides previously defined name: " << nameStr);
- return false;
- }
- return true;
- }
- bool CompileLibraryDef(const TAstNode& node, TContext& ctx) {
- if (node.GetChildrenCount() < 2 || node.GetChildrenCount() > 4) {
- ctx.AddError(node, "Expected list of size from 2 to 4");
- return false;
- }
- const auto name = node.GetChild(1);
- if (!name->IsAtom()) {
- ctx.AddError(*name, "Expected atom");
- return false;
- }
- TString url;
- TString token;
- if (node.GetChildrenCount() > 2) {
- const auto file = node.GetChild(2);
- if (!file->IsAtom()) {
- ctx.AddError(*file, "Expected atom");
- return false;
- }
- url = file->GetContent();
- if (node.GetChildrenCount() > 3) {
- const auto tokenNode = node.GetChild(3);
- if (!tokenNode->IsAtom()) {
- ctx.AddError(*tokenNode, "Expected atom");
- return false;
- }
- token = tokenNode->GetContent();
- }
- }
- if (url && !AddParameterDependencies(url, node, ctx)) {
- return false;
- }
- if (!ctx.ModuleResolver) {
- return true;
- }
- if (url) {
- if (!ctx.ModuleResolver->AddFromUrl(name->GetContent(), url, token, ctx.Expr, ctx.SyntaxVersion, 0, name->GetPosition())) {
- return false;
- }
- } else {
- if (!ctx.ModuleResolver->AddFromFile(name->GetContent(), ctx.Expr, ctx.SyntaxVersion, 0, name->GetPosition())) {
- return false;
- }
- }
- return true;
- }
- bool CompilePackageDef(const TAstNode& node, TContext& ctx) {
- if (node.GetChildrenCount() < 2 || node.GetChildrenCount() > 4) {
- ctx.AddError(node, "Expected list of size from 2 to 4");
- return false;
- }
- auto nameNode = node.GetChild(1);
- if (!nameNode->IsAtom()) {
- ctx.AddError(*nameNode, "Expected atom");
- return false;
- }
- auto name = TString(nameNode->GetContent());
- TString url;
- if (node.GetChildrenCount() > 2) {
- const auto file = node.GetChild(2);
- if (!file->IsAtom()) {
- ctx.AddError(*file, "Expected atom");
- return false;
- }
- url = file->GetContent();
- }
- TString token;
- if (node.GetChildrenCount() > 3) {
- const auto tokenNode = node.GetChild(3);
- if (!tokenNode->IsAtom()) {
- ctx.AddError(*tokenNode, "Expected atom");
- return false;
- }
- token = tokenNode->GetContent();
- }
- if (url && !AddParameterDependencies(url, node, ctx)) {
- return false;
- }
- if (!ctx.ModuleResolver) {
- return true;
- }
- if (!ctx.UrlListerManager) {
- return true;
- }
- ctx.ModuleResolver->RegisterPackage(name);
- auto packageModuleName = TStringBuilder() << PkgPrefix;
- TStringBuf nameBuf(name);
- while (auto part = nameBuf.NextTok(Dot)) {
- packageModuleName << Sep << part;
- }
- auto queue = TVector<std::pair<TString, TString>> {
- {packageModuleName, url}
- };
- while (queue) {
- auto [prefix, url] = queue.back();
- queue.pop_back();
- TVector<TUrlListEntry> urlListEntries;
- try {
- urlListEntries = ctx.UrlListerManager->ListUrl(url, token);
- } catch (const std::exception& e) {
- ctx.AddError(*nameNode,
- TStringBuilder()
- << "UrlListerManager: failed to list URL \"" << url
- << "\", details: " << e.what()
- );
- return false;
- }
- for (auto& urlListEntry: urlListEntries) {
- switch (urlListEntry.Type) {
- case EUrlListEntryType::FILE: {
- auto moduleName = TStringBuilder()
- << prefix << Sep << urlListEntry.Name;
- if (ctx.OverrideLibraries.contains(moduleName)) {
- continue;
- }
- if (!ctx.ModuleResolver->AddFromUrl(
- moduleName, urlListEntry.Url, token, ctx.Expr,
- ctx.SyntaxVersion, 0, nameNode->GetPosition()
- )) {
- return false;
- }
- break;
- }
- case EUrlListEntryType::DIRECTORY: {
- queue.push_back({
- TStringBuilder() << prefix << Sep << urlListEntry.Name,
- urlListEntry.Url
- });
- break;
- }
- }
- }
- }
- return true;
- }
- bool CompileOverrideLibraryDef(const TAstNode& node, TContext& ctx) {
- if (node.GetChildrenCount() != 2) {
- ctx.AddError(node, "Expected list of size 2");
- return false;
- }
- auto nameNode = node.GetChild(1);
- if (!nameNode->IsAtom()) {
- ctx.AddError(*nameNode, "Expected atom");
- return false;
- }
- if (!ctx.ModuleResolver) {
- return true;
- }
- auto overrideLibraryName = TStringBuilder()
- << PkgPrefix << Sep << nameNode->GetContent();
- if (!ctx.ModuleResolver->AddFromFile(
- overrideLibraryName, ctx.Expr, ctx.SyntaxVersion, 0, nameNode->GetPosition()
- )) {
- return false;
- }
- ctx.OverrideLibraries.insert(std::move(overrideLibraryName));
- return true;
- }
- bool CompileReturn(const TAstNode& node, TContext& ctx) {
- if (node.GetChildrenCount() < 2U) {
- ctx.AddError(node, "Expected non empty list.");
- return false;
- }
- TExprNode::TListType returns;
- returns.reserve(node.GetChildrenCount() - 1U);
- for (auto i = 1U; i < node.GetChildrenCount(); ++i) {
- auto r = Compile(*node.GetChild(i), ctx);
- if (r.empty())
- return false;
- std::move(r.begin(), r.end(), std::back_inserter(returns));
- }
- ctx.Frames.back().Return = std::move(returns);
- return true;
- }
- TExprNode::TListType CompileFunction(const TAstNode& root, TContext& ctx, bool topLevel = false) {
- if (!root.IsList()) {
- ctx.AddError(root, "Expected list");
- return {};
- }
- if (ctx.Frames.size() > 1000U) {
- ctx.AddError(root, "Too deep graph!");
- return {};
- }
- ctx.PushFrame();
- if (topLevel) {
- for (ui32 index = 0; index < root.GetChildrenCount(); ++index) {
- const auto node = root.GetChild(index);
- if (!node->IsList()) {
- ctx.AddError(*node, "Expected list");
- return {};
- }
- if (node->GetChildrenCount() == 0) {
- ctx.AddError(*node, "Expected not empty list");
- return {};
- }
- const auto firstChild = node->GetChild(0);
- if (!firstChild->IsAtom()) {
- ctx.AddError(*firstChild, "Expected atom");
- return {};
- }
- if (firstChild->GetContent() == TStringBuf("library")) {
- if (!CompileLibraryDef(*node, ctx))
- return {};
- } else if (firstChild->GetContent() == TStringBuf("set_package_version")) {
- if (!CompileSetPackageVersion(*node, ctx))
- return {};
- } else if (firstChild->GetContent() == TStringBuf("declare")) {
- if (!CompileDeclare(*node, ctx, false))
- return {};
- } else if (firstChild->GetContent() == TStringBuf("package")) {
- if (!CompilePackageDef(*node, ctx)) {
- return {};
- }
- } else if (firstChild->GetContent() == TStringBuf("override_library")) {
- if (!CompileOverrideLibraryDef(*node, ctx)) {
- return {};
- }
- }
- }
- if (ctx.ModuleResolver) {
- if (!ctx.ModuleResolver->Link(ctx.Expr)) {
- return {};
- }
- ctx.ModuleResolver->UpdateNextUniqueId(ctx.Expr);
- }
- }
- for (ui32 index = 0; index < root.GetChildrenCount(); ++index) {
- const auto node = root.GetChild(index);
- if (!ctx.Frames.back().Return.empty()) {
- ctx.Frames.back().Return.clear();
- ctx.AddError(*node, "Return is already exist");
- return {};
- }
- if (!node->IsList()) {
- ctx.AddError(*node, "Expected list");
- return {};
- }
- if (node->GetChildrenCount() == 0) {
- ctx.AddError(*node, "Expected not empty list");
- return {};
- }
- auto firstChild = node->GetChild(0);
- if (!firstChild->IsAtom()) {
- ctx.AddError(*firstChild, "Expected atom");
- return {};
- }
- if (firstChild->GetContent() == TStringBuf("let")) {
- if (!CompileLet(*node, ctx))
- return {};
- } else if (firstChild->GetContent() == TStringBuf("return")) {
- if (!CompileReturn(*node, ctx))
- return {};
- } else if (firstChild->GetContent() == TStringBuf("import")) {
- if (!CompileImport(*node, ctx))
- return {};
- } else if (firstChild->GetContent() == TStringBuf("declare")) {
- if (!topLevel) {
- ctx.AddError(*firstChild, "Declare statements are only allowed on top level block");
- return {};
- }
- if (!CompileDeclare(*node, ctx, true))
- return {};
- continue;
- } else if (firstChild->GetContent() == TStringBuf("library")) {
- if (!topLevel) {
- ctx.AddError(*firstChild, "Library statements are only allowed on top level block");
- return {};
- }
- continue;
- } else if (firstChild->GetContent() == TStringBuf("set_package_version")) {
- if (!topLevel) {
- ctx.AddError(*firstChild, "set_package_version statements are only allowed on top level block");
- return {};
- }
- continue;
- } else if (firstChild->GetContent() == TStringBuf("package")) {
- if (!topLevel) {
- ctx.AddError(*firstChild, "Package statements are only allowed on top level block");
- return {};
- }
- } else if (firstChild->GetContent() == TStringBuf("override_library")) {
- if (!topLevel) {
- ctx.AddError(*firstChild, "override_library statements are only allowed on top level block");
- return {};
- }
- } else {
- ctx.AddError(*firstChild, ToString("expected either let, return or import, but have ") + firstChild->GetContent());
- return {};
- }
- }
- auto ret = std::move(ctx.Frames.back().Return);
- ctx.PopFrame();
- if (ret.empty()) {
- ctx.AddError(root, "No return found");
- }
- return ret;
- }
- bool CompileLibrary(const TAstNode& root, TContext& ctx) {
- if (!root.IsList()) {
- ctx.AddError(root, "Expected list");
- return false;
- }
- ctx.PushFrame();
- for (ui32 index = 0; index < root.GetChildrenCount(); ++index) {
- const auto node = root.GetChild(index);
- if (!node->IsList()) {
- ctx.AddError(*node, "Expected list");
- return false;
- }
- if (node->GetChildrenCount() == 0) {
- ctx.AddError(*node, "Expected not empty list");
- return false;
- }
- auto firstChild = node->GetChild(0);
- if (!firstChild->IsAtom()) {
- ctx.AddError(*firstChild, "Expected atom");
- return false;
- }
- if (firstChild->GetContent() == TStringBuf("let")) {
- if (!CompileLet(*node, ctx))
- return false;
- } else if (firstChild->GetContent() == TStringBuf("import")) {
- if (!CompileImport(*node, ctx))
- return false;
- } else if (firstChild->GetContent() == TStringBuf("export")) {
- if (!CompileExport(*node, ctx))
- return false;
- } else {
- ctx.AddError(*firstChild, "expected either let, export or import");
- return false;
- }
- }
- ctx.PopFrame();
- return true;
- }
- TExprNode::TListType Compile(const TAstNode& node, TContext& ctx) {
- if (node.IsAtom()) {
- const auto foundNode = ctx.FindBinding(node.GetContent());
- if (foundNode.empty()) {
- ctx.AddError(node, TStringBuilder() << "Name not found: " << node.GetContent());
- return {};
- }
- return foundNode;
- }
- if (node.GetChildrenCount() == 0) {
- ctx.AddError(node, "Empty list, did you forget quote?");
- return {};
- }
- if (!node.GetChild(0)->IsAtom()) {
- ctx.AddError(node, "First item in list is not an atom, did you forget quote?");
- return {};
- }
- auto function = node.GetChild(0)->GetContent();
- if (function == TStringBuf("quote")) {
- if (node.GetChildrenCount() != 2) {
- ctx.AddError(node, "Quote should have one argument");
- return {};
- }
- if (auto quote = CompileQuote(*node.GetChild(1), ctx))
- return {std::move(quote)};
- return {};
- }
- if (function == TStringBuf("let") || function == TStringBuf("return")) {
- ctx.AddError(node, "Let and return should be used only at first level or inside def");
- return {};
- }
- if (function == TStringBuf("lambda")) {
- return CompileLambda(node, ctx);
- }
- if (function == TStringBuf("bind")) {
- if (auto bind = CompileBind(node, ctx))
- return {std::move(bind)};
- return {};
- }
- if (function == TStringBuf("block")) {
- if (node.GetChildrenCount() != 2) {
- ctx.AddError(node, "Block should have one argument");
- return {};
- }
- const auto quotedList = node.GetChild(1);
- if (quotedList->GetChildrenCount() != 2 || !quotedList->GetChild(0)->IsAtom() ||
- quotedList->GetChild(0)->GetContent() != TStringBuf("quote")) {
- ctx.AddError(node, "Expected quoted list");
- return {};
- }
- return CompileFunction(*quotedList->GetChild(1), ctx);
- }
- TExprNode::TListType children;
- children.reserve(node.GetChildrenCount() - 1U);
- for (auto index = 1U; index < node.GetChildrenCount(); ++index) {
- auto r = Compile(*node.GetChild(index), ctx);
- if (r.empty())
- return {};
- std::move(r.begin(), r.end(), std::back_inserter(children));
- }
- return {ctx.ProcessNode(node, ctx.Expr.NewCallable(node.GetPosition(), TString(function), std::move(children)))};
- }
- struct TFrameContext {
- size_t Index = 0;
- size_t Parent = 0;
- std::map<size_t, const TExprNode*> Nodes;
- std::vector<const TExprNode*> TopoSortedNodes;
- TNodeMap<TString> Bindings;
- };
- struct TVisitNodeContext {
- explicit TVisitNodeContext(TExprContext& expr)
- : Expr(expr)
- {}
- TExprContext& Expr;
- size_t Order = 0ULL;
- bool RefAtoms = false;
- bool AllowFreeArgs = false;
- bool NormalizeAtomFlags = false;
- TNodeMap<size_t> FreeArgs;
- std::unique_ptr<TMemoryPool> Pool;
- std::vector<TFrameContext> Frames;
- TFrameContext* CurrentFrame = nullptr;
- TNodeMap<size_t> LambdaFrames;
- std::map<TStringBuf, std::pair<const TExprNode*, TAstNode*>> Parameters;
- struct TCounters {
- size_t References = 0ULL, Neighbors = 0ULL, Order = 0ULL, Frame = 0ULL;
- };
- TNodeMap<TCounters> References;
- const TString& FindBinding(const TExprNode* node) const {
- for (const auto* frame = CurrentFrame; frame; frame = frame->Index > 0 ? &Frames[frame->Parent] : nullptr) {
- const auto it = frame->Bindings.find(node);
- if (frame->Bindings.cend() != it)
- return it->second;
- }
- static const TString stub;
- return stub;
- }
- size_t FindCommonAncestor(size_t one, size_t two) const {
- while (one && two) {
- if (one == two)
- return one;
- if (one > two)
- one = Frames[one].Parent;
- else
- two = Frames[two].Parent;
- }
- return 0ULL;
- }
- };
- void VisitArguments(const TExprNode& node, TVisitNodeContext& ctx) {
- YQL_ENSURE(node.Type() == TExprNode::Arguments);
- for (const auto& arg : node.Children()) {
- auto& counts = ctx.References[arg.Get()];
- ++counts.References;
- YQL_ENSURE(ctx.CurrentFrame->Nodes.emplace(counts.Order = ++ctx.Order, arg.Get()).second);
- }
- }
- void RevisitNode(const TExprNode& node, TVisitNodeContext& ctx);
- void RevisitNode(TVisitNodeContext::TCounters& counts, const TExprNode& node, TVisitNodeContext& ctx) {
- const auto nf = ctx.FindCommonAncestor(ctx.CurrentFrame->Index, counts.Frame);
- if (counts.Frame != nf) {
- auto& frame = ctx.Frames[counts.Frame = nf];
- frame.Nodes.emplace(counts.Order, &node);
- if (TExprNode::Lambda == node.Type()) {
- ctx.Frames[ctx.LambdaFrames[&node]].Parent = counts.Frame;
- } else {
- node.ForEachChild([&ctx](const TExprNode& child) {
- RevisitNode(child, ctx);
- });
- }
- }
- }
- void RevisitNode(const TExprNode& node, TVisitNodeContext& ctx) {
- if (TExprNode::Argument != node.Type()) {
- RevisitNode(ctx.References[&node], node, ctx);
- }
- }
- void VisitNode(const TExprNode& node, size_t neighbors, TVisitNodeContext& ctx) {
- if (TExprNode::Argument == node.Type())
- return;
- auto& counts = ctx.References[&node];
- counts.Neighbors += neighbors;
- if (counts.References++) {
- RevisitNode(counts, node, ctx);
- } else {
- counts.Frame = ctx.CurrentFrame->Index;
- if (node.Type() == TExprNode::Lambda) {
- YQL_ENSURE(node.ChildrenSize() > 0U);
- const auto index = ctx.Frames.size();
- if (ctx.LambdaFrames.emplace(&node, index).second) {
- const auto prevFrameIndex = ctx.CurrentFrame - &ctx.Frames.front();
- const auto parentIndex = ctx.CurrentFrame->Index;
- ctx.Frames.emplace_back();
- ctx.CurrentFrame = &ctx.Frames.back();
- ctx.CurrentFrame->Index = index;
- ctx.CurrentFrame->Parent = parentIndex;
- VisitArguments(node.Head(), ctx);
- for(ui32 i = 1U; i < node.ChildrenSize(); ++i) {
- VisitNode(*node.Child(i), node.ChildrenSize() - 1U, ctx);
- }
- ctx.CurrentFrame = &ctx.Frames.front() + prevFrameIndex;
- }
- } else {
- node.ForEachChild([&](const TExprNode& child) {
- VisitNode(child, node.ChildrenSize(), ctx);
- });
- }
- if (!counts.Order)
- counts.Order = ++ctx.Order;
- ctx.CurrentFrame->Nodes.emplace(counts.Order, &node);
- }
- }
- using TRoots = TSmallVec<const TExprNode*>;
- TAstNode* ConvertFunction(TPositionHandle position, const TRoots& roots, TVisitNodeContext& ctx, ui32 annotationFlags, TMemoryPool& pool);
- TAstNode* BuildValueNode(const TExprNode& node, TVisitNodeContext& ctx, const TString& topLevelName, ui32 annotationFlags, TMemoryPool& pool, bool useBindings) {
- TAstNode* res = nullptr;
- const auto& name = ctx.FindBinding(&node);
- if (!name.empty() && name != topLevelName && useBindings) {
- res = TAstNode::NewAtom(ctx.Expr.GetPosition(node.Pos()), name, pool);
- } else {
- switch (node.Type()) {
- case TExprNode::Atom:
- {
- auto quote = AnnotateAstNode(&TAstNode::QuoteAtom, nullptr, annotationFlags, pool, ctx.RefAtoms);
- auto flags = ctx.NormalizeAtomFlags ? TNodeFlags::ArbitraryContent : node.Flags();
- auto content = AnnotateAstNode(
- ctx.RefAtoms ?
- TAstNode::NewLiteralAtom(ctx.Expr.GetPosition(node.Pos()), node.Content(), pool, flags) :
- TAstNode::NewAtom(ctx.Expr.GetPosition(node.Pos()), node.Content(), pool, flags),
- &node, annotationFlags, pool, ctx.RefAtoms);
- res = TAstNode::NewList(ctx.Expr.GetPosition(node.Pos()), pool, quote, content);
- break;
- }
- case TExprNode::List:
- {
- TSmallVec<TAstNode*> values;
- for (const auto& child : node.Children()) {
- values.push_back(BuildValueNode(*child, ctx, topLevelName, annotationFlags, pool, useBindings));
- }
- auto quote = AnnotateAstNode(&TAstNode::QuoteAtom, nullptr, annotationFlags, pool, ctx.RefAtoms);
- auto list = AnnotateAstNode(TAstNode::NewList(
- ctx.Expr.GetPosition(node.Pos()), values.data(), values.size(), pool), &node, annotationFlags, pool, ctx.RefAtoms);
- res = TAstNode::NewList(ctx.Expr.GetPosition(node.Pos()), pool, quote, list);
- break;
- }
- case TExprNode::Callable:
- {
- if (node.Content() == "Parameter") {
- const auto& nameNode = *node.Child(0);
- const auto& typeNode = *node.Child(1);
- Y_UNUSED(typeNode);
- res = TAstNode::NewAtom(ctx.Expr.GetPosition(node.Pos()), nameNode.Content(), pool);
- auto it = ctx.Parameters.find(nameNode.Content());
- if (it != ctx.Parameters.end()) {
- break;
- }
- auto declareAtom = TAstNode::NewLiteralAtom(ctx.Expr.GetPosition(node.Pos()), TStringBuf("declare"), pool);
- auto nameAtom = ctx.RefAtoms
- ? TAstNode::NewLiteralAtom(ctx.Expr.GetPosition(nameNode.Pos()), nameNode.Content(), pool)
- : TAstNode::NewAtom(ctx.Expr.GetPosition(nameNode.Pos()), nameNode.Content(), pool);
- TSmallVec<TAstNode*> children;
- children.push_back(AnnotateAstNode(declareAtom, nullptr, annotationFlags, pool, ctx.RefAtoms));
- children.push_back(AnnotateAstNode(nameAtom, nullptr, annotationFlags, pool, ctx.RefAtoms));
- children.push_back(BuildValueNode(typeNode, ctx, topLevelName, annotationFlags, pool, false));
- auto declareNode = TAstNode::NewList(ctx.Expr.GetPosition(node.Pos()), children.data(), children.size(), pool);
- declareNode = AnnotateAstNode(declareNode, &node, annotationFlags, pool, ctx.RefAtoms);
- ctx.Parameters.insert(std::make_pair(nameNode.Content(),
- std::make_pair(&typeNode, declareNode)));
- break;
- }
- TSmallVec<TAstNode*> children;
- children.push_back(AnnotateAstNode(
- ctx.RefAtoms ?
- TAstNode::NewLiteralAtom(ctx.Expr.GetPosition(node.Pos()), node.Content(), pool) :
- TAstNode::NewAtom(ctx.Expr.GetPosition(node.Pos()), node.Content(), pool),
- nullptr, annotationFlags, pool, ctx.RefAtoms));
- for (const auto& child : node.Children()) {
- children.push_back(BuildValueNode(*child, ctx, topLevelName, annotationFlags, pool, useBindings));
- }
- res = TAstNode::NewList(ctx.Expr.GetPosition(node.Pos()), children.data(), children.size(), pool);
- break;
- }
- case TExprNode::Lambda:
- {
- const auto prevFrame = ctx.CurrentFrame;
- const auto it = ctx.LambdaFrames.find(&node);
- YQL_ENSURE(it != ctx.LambdaFrames.end());
- ctx.CurrentFrame = &ctx.Frames[it->second];
- YQL_ENSURE(node.ChildrenSize() > 0U);
- const auto& args = node.Head();
- TSmallVec<TAstNode*> argsChildren;
- for (const auto& arg : args.Children()) {
- const auto& name = ctx.FindBinding(arg.Get());
- const auto atom = TAstNode::NewAtom(ctx.Expr.GetPosition(node.Pos()), name, pool);
- argsChildren.emplace_back(AnnotateAstNode(atom, arg.Get(), annotationFlags, pool, ctx.RefAtoms));
- }
- auto argsNode = TAstNode::NewList(ctx.Expr.GetPosition(args.Pos()), argsChildren.data(), argsChildren.size(), pool);
- auto argsContainer = TAstNode::NewList(ctx.Expr.GetPosition(args.Pos()), pool,
- AnnotateAstNode(&TAstNode::QuoteAtom, nullptr, annotationFlags, pool, ctx.RefAtoms),
- AnnotateAstNode(argsNode, nullptr, annotationFlags, pool, ctx.RefAtoms));
- const bool block = ctx.CurrentFrame->Bindings.cend() != std::find_if(ctx.CurrentFrame->Bindings.cbegin(), ctx.CurrentFrame->Bindings.cend(),
- [](const auto& bind) { return bind.first->Type() != TExprNode::Argument; }
- );
- if (block) {
- TSmallVec<const TExprNode*> body(node.ChildrenSize() - 1U);
- for (ui32 i = 0U; i < body.size(); ++i)
- body[i] = node.Child(i + 1U);
- const auto blockNode = TAstNode::NewLiteralAtom(ctx.Expr.GetPosition(node.Pos()), TStringBuf("block"), pool);
- const auto quotedListNode = TAstNode::NewList(ctx.Expr.GetPosition(node.Pos()), pool,
- AnnotateAstNode(&TAstNode::QuoteAtom, nullptr, annotationFlags, pool, ctx.RefAtoms),
- ConvertFunction(node.Pos(), body, ctx, annotationFlags, pool));
- const auto blockBody = TAstNode::NewList(ctx.Expr.GetPosition(node.Pos()), pool,
- AnnotateAstNode(blockNode, nullptr, annotationFlags, pool, ctx.RefAtoms),
- AnnotateAstNode(quotedListNode, nullptr, annotationFlags, pool, ctx.RefAtoms));
- res = AnnotateAstNode(blockBody, nullptr, annotationFlags, pool, ctx.RefAtoms);
- ctx.CurrentFrame = prevFrame;
- res = TAstNode::NewList(ctx.Expr.GetPosition(node.Pos()), pool,
- AnnotateAstNode(TAstNode::NewLiteralAtom(
- ctx.Expr.GetPosition(node.Pos()), TStringBuf("lambda"), pool), nullptr, annotationFlags, pool, ctx.RefAtoms),
- AnnotateAstNode(argsContainer, &args, annotationFlags, pool, ctx.RefAtoms),
- res);
- } else {
- TSmallVec<TAstNode*> children(node.ChildrenSize() + 1U);
- for (ui32 i = 1U; i < node.ChildrenSize(); ++i) {
- children[i + 1U] = BuildValueNode(*node.Child(i), ctx, topLevelName, annotationFlags, pool, useBindings);
- }
- ctx.CurrentFrame = prevFrame;
- children[0] = AnnotateAstNode(TAstNode::NewLiteralAtom(
- ctx.Expr.GetPosition(node.Pos()), TStringBuf("lambda"), pool), nullptr, annotationFlags, pool, ctx.RefAtoms);
- children[1] = AnnotateAstNode(argsContainer, &args, annotationFlags, pool, ctx.RefAtoms);
- res = TAstNode::NewList(ctx.Expr.GetPosition(node.Pos()), children.data(), children.size(), pool);
- }
- break;
- }
- case TExprNode::World:
- res = TAstNode::NewLiteralAtom(ctx.Expr.GetPosition(node.Pos()), TStringBuf("world"), pool);
- break;
- case TExprNode::Argument: {
- YQL_ENSURE(ctx.AllowFreeArgs, "Free arguments are not allowed");
- auto iter = ctx.FreeArgs.emplace(&node, ctx.FreeArgs.size());
- res = TAstNode::NewLiteralAtom(ctx.Expr.GetPosition(node.Pos()), ctx.Expr.AppendString("_FreeArg" + ToString(iter.first->second)), pool);
- break;
- }
- default:
- YQL_ENSURE(false, "Unknown type: " << static_cast<ui32>(node.Type()));
- }
- }
- return AnnotateAstNode(res, &node, annotationFlags, pool, ctx.RefAtoms);
- }
- TAstNode* ConvertFunction(TPositionHandle position, const TRoots& roots, TVisitNodeContext& ctx, ui32 annotationFlags, TMemoryPool& pool) {
- YQL_ENSURE(!roots.empty(), "Missed roots.");
- TSmallVec<TAstNode*> children;
- for (const auto& node : ctx.CurrentFrame->TopoSortedNodes) {
- const auto& name = ctx.FindBinding(node);
- if (name.empty() || node->Type() == TExprNode::Arguments || node->Type() == TExprNode::Argument) {
- continue;
- }
- const auto letAtom = TAstNode::NewLiteralAtom(ctx.Expr.GetPosition(node->Pos()), TStringBuf("let"), pool);
- const auto nameAtom = TAstNode::NewAtom(ctx.Expr.GetPosition(node->Pos()), name, pool);
- const auto valueNode = BuildValueNode(*node, ctx, name, annotationFlags, pool, true);
- const auto letNode = TAstNode::NewList(ctx.Expr.GetPosition(node->Pos()), pool,
- AnnotateAstNode(letAtom, nullptr, annotationFlags, pool, ctx.RefAtoms),
- AnnotateAstNode(nameAtom, nullptr, annotationFlags, pool, ctx.RefAtoms),
- valueNode);
- children.push_back(AnnotateAstNode(letNode, nullptr, annotationFlags, pool, ctx.RefAtoms));
- }
- const auto returnAtom = TAstNode::NewLiteralAtom(ctx.Expr.GetPosition(position), TStringBuf("return"), pool);
- TSmallVec<TAstNode*> returnChildren;
- returnChildren.reserve(roots.size() + 1U);
- returnChildren.emplace_back(AnnotateAstNode(returnAtom, nullptr, annotationFlags, pool, ctx.RefAtoms));
- for (const auto root : roots) {
- returnChildren.emplace_back(BuildValueNode(*root, ctx, TString(), annotationFlags, pool, true));
- }
- const auto returnList = TAstNode::NewList(ctx.Expr.GetPosition(position), returnChildren.data(), returnChildren.size(), pool);
- children.emplace_back(AnnotateAstNode(returnList, 1U == roots.size() ? roots.front() : nullptr, annotationFlags, pool, ctx.RefAtoms));
- if (!ctx.CurrentFrame->Index && !ctx.Parameters.empty()) {
- TSmallVec<TAstNode*> parameterNodes;
- parameterNodes.reserve(ctx.Parameters.size());
- for (auto& pair : ctx.Parameters) {
- parameterNodes.push_back(pair.second.second);
- }
- children.insert(children.begin(), parameterNodes.begin(), parameterNodes.end());
- }
- const auto res = TAstNode::NewList(ctx.Expr.GetPosition(position), children.data(), children.size(), pool);
- return AnnotateAstNode(res, nullptr, annotationFlags, pool, ctx.RefAtoms);
- }
- bool InlineNode(const TExprNode& node, size_t references, size_t neighbors, const TConvertToAstSettings& settings) {
- if (settings.NoInlineFunc) {
- if (settings.NoInlineFunc(node)) {
- return false;
- }
- }
- switch (node.Type()) {
- case TExprNode::Argument:
- return false;
- case TExprNode::Atom:
- if (const auto flags = node.Flags()) {
- if ((TNodeFlags::BinaryContent | TNodeFlags::MultilineContent) & flags)
- return false;
- else {
- if (TNodeFlags::ArbitraryContent & flags)
- return node.Content().length() <= (references == 1U ? 0x40U : 0x10U);
- else
- return true;
- }
- } else
- return true;
- default:
- if (neighbors < 2U)
- return true;
- if (const auto children = node.ChildrenSize())
- return references == 1U && children < 3U;
- else
- return true;
- }
- }
- typedef std::pair<const TExprNode*, const TExprNode*> TPairOfNodePotinters;
- typedef std::unordered_set<TPairOfNodePotinters, THash<TPairOfNodePotinters>> TNodesPairSet;
- typedef TNodeMap<std::pair<ui32, ui32>> TArgumentsMap;
- bool CompareExpressions(const TExprNode*& one, const TExprNode*& two, TArgumentsMap& argumentsMap, ui32 level, TNodesPairSet& visited) {
- const auto ins = visited.emplace(one, two);
- if (!ins.second) {
- return true;
- }
- if (one->Type() != two->Type())
- return false;
- if (one->ChildrenSize() != two->ChildrenSize())
- return false;
- switch (two->Type()) {
- case TExprNode::Arguments: {
- ui32 i1 = 0U, i2 = 0U;
- one->ForEachChild([&](const TExprNode& arg){ argumentsMap.emplace(&arg, std::make_pair(level, ++i1)); });
- two->ForEachChild([&](const TExprNode& arg){ argumentsMap.emplace(&arg, std::make_pair(level, ++i2)); });
- return true;
- }
- case TExprNode::Argument:
- if (const auto oneArg = argumentsMap.find(one), twoArg = argumentsMap.find(two); oneArg == twoArg)
- return argumentsMap.cend() != oneArg || one == two;
- else if (argumentsMap.cend() != oneArg && argumentsMap.cend() != twoArg) {
- return oneArg->second == twoArg->second;
- }
- return false;
- case TExprNode::Atom:
- if (one->GetFlagsToCompare() != two->GetFlagsToCompare())
- return false;
- [[fallthrough]]; // AUTOGENERATED_FALLTHROUGH_FIXME
- case TExprNode::Callable:
- if (one->Content() != two->Content())
- return false;
- [[fallthrough]]; // AUTOGENERATED_FALLTHROUGH_FIXME
- default:
- break;
- case TExprNode::Lambda:
- ++level;
- }
- if (const auto childs = one->ChildrenSize()) {
- const auto& l = one->Children();
- const auto& r = two->Children();
- for (ui32 i = 0U; i < childs; ++i) {
- if (!CompareExpressions(one = l[i].Get(), two = r[i].Get(), argumentsMap, level, visited)) {
- return false;
- }
- }
- }
- return true;
- }
- using TNodeSetPtr = std::shared_ptr<TNodeSet>;
- TNodeSetPtr ExcludeFromUnresolved(const TExprNode& args, const TNodeSetPtr& unresolved) {
- if (!unresolved || unresolved->empty() || args.ChildrenSize() == 0) {
- return unresolved;
- }
- size_t excluded = 0;
- auto newUnresolved = std::make_shared<TNodeSet>(*unresolved);
- for (auto& toExclude : args.Children()) {
- excluded += newUnresolved->erase(toExclude.Get());
- }
- return excluded ? newUnresolved : unresolved;
- }
- TNodeSetPtr MergeUnresolvedArgs(const TNodeSetPtr& one, const TNodeSetPtr& two) {
- if (!one || one->empty()) {
- return two;
- }
- if (!two || two->empty()) {
- return one;
- }
- const TNodeSetPtr& bigger = (one->size() > two->size()) ? one : two;
- const TNodeSetPtr& smaller = (one->size() > two->size()) ? two : one;
- TNodeSetPtr result = std::make_shared<TNodeSet>(*bigger);
- bool inserted = false;
- for (auto& item : *smaller) {
- if (result->insert(item).second) {
- inserted = true;
- }
- }
- return inserted ? result : bigger;
- }
- TNodeSetPtr CollectUnresolvedArgs(const TExprNode& root, TNodeMap<TNodeSetPtr>& unresolvedArgs, TNodeSet& allArgs) {
- auto it = unresolvedArgs.find(&root);
- if (it != unresolvedArgs.end()) {
- return it->second;
- }
- TNodeSetPtr result;
- switch (root.Type()) {
- case TExprNode::Argument:
- result = std::make_shared<TNodeSet>(TNodeSet{&root});
- break;
- case TExprNode::Lambda:
- {
- if (!root.ChildrenSize()) {
- ythrow yexception() << "lambda #" << root.UniqueId() << " has " << root.ChildrenSize() << " children";
- }
- const auto& arguments = root.Head();
- if (arguments.Type() != TExprNode::Arguments) {
- ythrow yexception() << "unexpected type of arguments node in lambda #" << root.UniqueId();
- }
- arguments.ForEachChild([&](const TExprNode& arg) {
- if (arg.Type() != TExprNode::Argument) {
- ythrow yexception() << "expecting argument, #[" << arg.UniqueId() << "]";
- }
- if (!allArgs.insert(&arg).second) {
- ythrow yexception() << "argument is duplicated, #[" << arg.UniqueId() << "]";
- }
- });
- for (ui32 i = 1U; i < root.ChildrenSize(); ++i) {
- const auto bodyUnresolvedArgs = CollectUnresolvedArgs(*root.Child(i), unresolvedArgs, allArgs);
- result = ExcludeFromUnresolved(arguments, bodyUnresolvedArgs);
- }
- break;
- }
- case TExprNode::Callable:
- case TExprNode::List:
- {
- root.ForEachChild([&](const TExprNode& child) {
- result = MergeUnresolvedArgs(result, CollectUnresolvedArgs(child, unresolvedArgs, allArgs));
- });
- break;
- }
- case TExprNode::Atom:
- case TExprNode::World:
- break;
- case TExprNode::Arguments:
- ythrow yexception() << "unexpected free arguments node #[" << root.UniqueId() << "]";
- break;
- }
- unresolvedArgs[&root] = result;
- return result;
- }
- typedef TNodeMap<long> TRefCountsMap;
- void CalculateReferences(const TExprNode& node, TRefCountsMap& refCounts) {
- if (!refCounts[&node]++)
- for (const auto& child : node.Children())
- CalculateReferences(*child, refCounts);
- }
- void CheckReferences(const TExprNode& node, TRefCountsMap& refCounts, TNodeSet& visited) {
- if (visited.emplace(&node).second) {
- for (const auto& child : node.Children()) {
- YQL_ENSURE(child->UseCount() == refCounts[child.Get()]);
- CheckReferences(*child, refCounts, visited);
- }
- }
- }
- bool GatherParentsImpl(const TExprNode& node, TParentsMap& parentsMap, TNodeSet& visited) {
- if (node.Type() == TExprNode::Arguments || node.Type() == TExprNode::Atom || node.Type() == TExprNode::World) {
- return false;
- }
- if (!visited.emplace(&node).second) {
- return true;
- }
- node.ForEachChild([&](const TExprNode& child) {
- if (GatherParentsImpl(child, parentsMap, visited)) {
- parentsMap[&child].emplace(&node);
- }
- });
- return true;
- }
- } // namespace
- bool CompileExpr(TAstNode& astRoot, TExprNode::TPtr& exprRoot, TExprContext& ctx,
- IModuleResolver* resolver, IUrlListerManager* urlListerManager,
- bool hasAnnotations, ui32 typeAnnotationIndex, ui16 syntaxVersion) {
- exprRoot.Reset();
- TAstNode* cleanRoot = nullptr;
- TAnnotationNodeMap annotations;
- const TAnnotationNodeMap* currentAnnotations = nullptr;
- TAstParseResult cleanupRes;
- if (!hasAnnotations) {
- typeAnnotationIndex = Max<ui32>();
- cleanRoot = &astRoot;
- currentAnnotations = nullptr;
- } else if (typeAnnotationIndex != Max<ui32>()) {
- cleanupRes.Pool = std::make_unique<TMemoryPool>(4096);
- cleanRoot = ExtractAnnotations(astRoot, annotations, *cleanupRes.Pool);
- cleanupRes.Root = cleanRoot;
- currentAnnotations = &annotations;
- } else {
- cleanupRes.Pool = std::make_unique<TMemoryPool>(4096);
- cleanRoot = RemoveAnnotations(astRoot, *cleanupRes.Pool);
- cleanupRes.Root = cleanRoot;
- currentAnnotations = nullptr;
- }
- if (!cleanRoot) {
- return false;
- }
- TContext compileCtx(ctx);
- compileCtx.SyntaxVersion = syntaxVersion;
- compileCtx.Annotations = currentAnnotations;
- compileCtx.TypeAnnotationIndex = typeAnnotationIndex;
- compileCtx.ModuleResolver = resolver;
- compileCtx.UrlListerManager = urlListerManager;
- compileCtx.PushFrame();
- auto world = compileCtx.Expr.NewWorld(astRoot.GetPosition());
- if (typeAnnotationIndex != Max<ui32>()) {
- world->SetTypeAnn(compileCtx.Expr.MakeType<TWorldExprType>());
- }
- compileCtx.Frames.back().Bindings[TStringBuf("world")] = {std::move(world)};
- auto ret = CompileFunction(*cleanRoot, compileCtx, true);
- if (1U != ret.size())
- return false;
- exprRoot = std::move(ret.front());
- compileCtx.PopFrame();
- return bool(exprRoot);
- }
- bool CompileExpr(TAstNode& astRoot, TExprNode::TPtr& exprRoot, TExprContext& ctx,
- IModuleResolver* resolver, IUrlListerManager* urlListerManager,
- ui32 annotationFlags, ui16 syntaxVersion)
- {
- bool hasAnnotations = annotationFlags != TExprAnnotationFlags::None;
- ui32 typeAnnotationIndex = Max<ui32>();
- if (annotationFlags & TExprAnnotationFlags::Types) {
- bool hasPostions = annotationFlags & TExprAnnotationFlags::Position;
- typeAnnotationIndex = hasPostions ? 1 : 0;
- }
- return CompileExpr(astRoot, exprRoot, ctx, resolver, urlListerManager, hasAnnotations, typeAnnotationIndex, syntaxVersion);
- }
- bool CompileExpr(TAstNode& astRoot, TLibraryCohesion& library, TExprContext& ctx, ui16 syntaxVersion) {
- const TAstNode* cleanRoot = &astRoot;
- TContext compileCtx(ctx);
- compileCtx.Annotations = nullptr;
- compileCtx.TypeAnnotationIndex = Max<ui32>();
- compileCtx.SyntaxVersion = syntaxVersion;
- const bool ok = CompileLibrary(*cleanRoot, compileCtx);
- library = compileCtx.Cohesion;
- return ok;
- }
- const TTypeAnnotationNode* CompileTypeAnnotation(const TAstNode& node, TExprContext& ctx) {
- TContext compileCtx(ctx);
- return compileCtx.CompileTypeAnnotationNode(node);
- }
- template<class Set>
- bool IsDependedImpl(const TExprNode& node, const Set& dependences, TNodeSet& visited) {
- if (!visited.emplace(&node).second)
- return false;
- if (dependences.cend() != dependences.find(&node))
- return true;
- for (const auto& child : node.Children()) {
- if (IsDependedImpl(*child, dependences, visited))
- return true;
- }
- return false;
- }
- namespace {
- enum EChangeState : ui8 {
- Unknown = 0,
- Changed = 1,
- Unchanged = 2
- };
- ui64 CalcBloom(const ui64 id) {
- return 1ULL |
- (2ULL << (std::hash<ui64>()(id) % 63ULL)) |
- (2ULL << (IntHash<ui64>(id) % 63ULL)) |
- (2ULL << (FnvHash<ui64>(&id, sizeof(id)) % 63ULL)) |
- (2ULL << (MurmurHash<ui64>(&id, sizeof(id)) % 63ULL)) |
- (2ULL << (CityHash64(reinterpret_cast<const char*>(&id), sizeof(id)) % 63ULL));
- }
- inline bool InBloom(const ui64 set, const ui64 bloom) {
- return (bloom >> 1) == ((bloom & set) >> 1);
- }
- EChangeState GetChanges(TExprNode* start, const TNodeOnNodeOwnedMap& replaces, const TNodeMap<TNodeOnNodeOwnedMap>& localReplaces,
- TNodeMap<EChangeState>& changes, TNodeMap<bool>& updatedLambdas);
- EChangeState DoGetChanges(TExprNode* start, const TNodeOnNodeOwnedMap& replaces, const TNodeMap<TNodeOnNodeOwnedMap>& localReplaces,
- TNodeMap<EChangeState>& changes, TNodeMap<bool>& updatedLambdas) {
- if (start->GetBloom() & 1ULL) {
- bool maybe = false;
- for (const auto& repl : replaces) {
- if (repl.second && !repl.first->Dead()) {
- if (TExprNode::Argument != repl.first->Type()) {
- maybe = true;
- break;
- }
- if (!repl.first->GetBloom())
- const_cast<TExprNode*>(repl.first)->SetBloom(CalcBloom(repl.first->UniqueId()));
- if (InBloom(start->GetBloom(), repl.first->GetBloom())) {
- maybe = true;
- break;
- }
- }
- }
- if (!maybe) {
- return EChangeState::Unchanged;
- }
- }
- start->SetBloom(1ULL);
- ui32 combinedState = EChangeState::Unchanged;
- bool incompleteBloom = false;
- start->ForEachChild([&](TExprNode& child) {
- combinedState |= GetChanges(&child, replaces, localReplaces, changes, updatedLambdas);
- start->SetBloom(start->GetBloom() | child.GetBloom());
- incompleteBloom = incompleteBloom || (child.Type() != TExprNode::Arguments && !child.GetBloom());
- });
- if (incompleteBloom) {
- start->SetBloom(0ULL);
- }
- return (EChangeState)combinedState;
- }
- EChangeState GetChanges(TExprNode* start, const TNodeOnNodeOwnedMap& replaces, const TNodeMap<TNodeOnNodeOwnedMap>& localReplaces,
- TNodeMap<EChangeState>& changes, TNodeMap<bool>& updatedLambdas) {
- if (start->Type() == TExprNode::Arguments) {
- return EChangeState::Unchanged;
- }
- if (!start->GetBloom() && TExprNode::Argument == start->Type()) {
- start->SetBloom(CalcBloom(start->UniqueId()));
- }
- auto& state = changes[start];
- if (state != EChangeState::Unknown) {
- return state;
- }
- if (const auto it = replaces.find(start); it != replaces.cend()) {
- return state = it->second ? EChangeState::Changed : EChangeState::Unchanged;
- }
- if (start->ChildrenSize() == 0) {
- return state = EChangeState::Unchanged;
- }
- if (start->Type() == TExprNode::Lambda) {
- TNodeOnNodeOwnedMap newReplaces = replaces;
- start->Head().ForEachChild([&](const TExprNode& arg){ newReplaces[&arg] = {}; });
- const auto locIt = localReplaces.find(start);
- if (locIt != localReplaces.end()) {
- for (auto& r: locIt->second) {
- newReplaces[r.first] = r.second;
- }
- }
- state = DoGetChanges(start, newReplaces, localReplaces, changes, updatedLambdas);
- if ((state & EChangeState::Changed) != 0) {
- updatedLambdas.emplace(start, false);
- }
- return state;
- }
- return state = DoGetChanges(start, replaces, localReplaces, changes, updatedLambdas);
- }
- template<bool KeepTypeAnns>
- TExprNode::TPtr DoReplace(const TExprNode::TPtr& start, const TNodeOnNodeOwnedMap& replaces,
- const TNodeOnNodeOwnedMap& argReplaces, const TNodeMap<TNodeOnNodeOwnedMap>& localReplaces,
- TNodeMap<EChangeState>& changes, TNodeOnNodeOwnedMap& processed, TExprContext& ctx)
- {
- auto& target = processed[start.Get()];
- if (target) {
- return target;
- }
- TMaybe<TExprNode::TPtr> replace;
- const auto it = replaces.find(start.Get());
- if (it != replaces.end()) {
- replace = it->second;
- }
- const auto argIt = argReplaces.find(start.Get());
- if (argIt != argReplaces.end()) {
- YQL_ENSURE(!replace.Defined());
- replace = argIt->second;
- }
- if (replace.Defined()) {
- if (*replace) {
- return target = ctx.ReplaceNodes(std::move(*replace), argReplaces);
- }
- return target = start;
- }
- if (start->ChildrenSize() != 0) {
- auto changeIt = changes.find(start.Get());
- YQL_ENSURE(changeIt != changes.end(), "Missing change");
- const bool isChanged = (changeIt->second & EChangeState::Changed) != 0;
- if (isChanged) {
- if (start->Type() == TExprNode::Lambda) {
- TNodeOnNodeOwnedMap newArgReplaces = argReplaces;
- const auto locIt = localReplaces.find(start.Get());
- YQL_ENSURE(locIt != localReplaces.end(), "Missing local changes");
- for (auto& r: locIt->second) {
- newArgReplaces[r.first] = r.second;
- }
- const auto& args = start->Head();
- TExprNode::TListType newArgsList;
- newArgsList.reserve(args.ChildrenSize());
- args.ForEachChild([&](const TExprNode& arg) {
- const auto argIt = newArgReplaces.find(&arg);
- YQL_ENSURE(argIt != newArgReplaces.end(), "Missing argument");
- processed.emplace(&arg, argIt->second);
- newArgsList.emplace_back(argIt->second);
- });
- auto newBody = GetLambdaBody(*start);
- std::for_each(newBody.begin(), newBody.end(), [&](TExprNode::TPtr& node) {
- node = DoReplace<KeepTypeAnns>(node, replaces, newArgReplaces, localReplaces,
- changes, processed, ctx);
- });
- auto newArgs = ctx.NewArguments(start->Pos(), std::move(newArgsList));
- if constexpr (KeepTypeAnns)
- newArgs->SetTypeAnn(ctx.MakeType<TUnitExprType>());
- target = ctx.NewLambda(start->Pos(), std::move(newArgs), std::move(newBody));
- if constexpr (KeepTypeAnns)
- target->SetTypeAnn(start->GetTypeAnn());
- return target;
- } else {
- bool replaced = false;
- TExprNode::TListType newChildren;
- newChildren.reserve(start->ChildrenSize());
- for (const auto& child : start->Children()) {
- auto newChild = DoReplace<KeepTypeAnns>(child, replaces, argReplaces, localReplaces,
- changes, processed, ctx);
- if (newChild != child)
- replaced = true;
- newChildren.emplace_back(std::move(newChild));
- }
- if (replaced) {
- target = ctx.ChangeChildren(*start, std::move(newChildren));
- if constexpr (KeepTypeAnns)
- target->SetTypeAnn(start->GetTypeAnn());
- return target;
- }
- }
- }
- }
- return target = start;
- }
- void EnsureNoBadReplaces(const TExprNode& start, const TNodeOnNodeOwnedMap& replaces, TNodeSet&& visited = TNodeSet()) {
- if (!visited.insert(&start).second) {
- return;
- }
- const auto it = replaces.find(&start);
- if (it != replaces.end() && it->second) {
- ythrow yexception() << "Bad replace for node: " << start.UniqueId() << "\n";
- }
- if (start.Type() == TExprNode::Lambda) {
- TNodeOnNodeOwnedMap newReplaces = replaces;
- start.Head().ForEachChild([&](const TExprNode& arg){ newReplaces[&arg] = {}; });
- start.ForEachChild([&](const TExprNode& child){ EnsureNoBadReplaces(child, newReplaces, std::move(visited)); });
- } else {
- start.ForEachChild([&](const TExprNode& child){ EnsureNoBadReplaces(child, replaces, std::move(visited)); });
- }
- }
- const bool InternalDebug = false;
- template<bool KeepTypeAnns>
- TExprNode::TPtr ReplaceNodesImpl(TExprNode::TPtr&& start, const TNodeOnNodeOwnedMap& replaces, TNodeOnNodeOwnedMap& processed, TExprContext& ctx) {
- if (InternalDebug) {
- Cerr << "Before\n" << start->Dump() << "\n";
- Cerr << "Replaces\n";
- ui32 rep = 0;
- for (auto& x : replaces) {
- if (x.second) {
- Cerr << "#" << ++rep << " " << x.first->Dump() << "\n into " << x.second->Dump() << "\n";
- }
- }
- }
- TNodeMap<EChangeState> changes;
- TNodeMap<bool> updatedLambdas;
- TNodeMap<TNodeOnNodeOwnedMap> localReplaces;
- if ((GetChanges(start.Get(), replaces, localReplaces, changes, updatedLambdas) & EChangeState::Changed) == 0) {
- return std::move(start);
- }
- if (!updatedLambdas.empty()) {
- for (;;) {
- changes.clear();
- for (auto& x : updatedLambdas) {
- if (!x.second) {
- TNodeOnNodeOwnedMap& lambdaReplaces = localReplaces[x.first];
- const auto& args = x.first->Head();
- args.ForEachChild([&](const TExprNode& arg) {
- const auto newArg = lambdaReplaces.emplace(&arg, ctx.ShallowCopy(arg)).first->second;
- if constexpr (KeepTypeAnns)
- newArg->SetTypeAnn(arg.GetTypeAnn());
- });
- x.second = true;
- }
- }
- auto prevSize = updatedLambdas.size();
- GetChanges(start.Get(), replaces, localReplaces, changes, updatedLambdas);
- if (updatedLambdas.size() == prevSize) {
- break;
- }
- }
- }
- auto ret = DoReplace<KeepTypeAnns>(start, replaces, {}, localReplaces, changes, processed, ctx);
- if (InternalDebug) {
- Cerr << "After\n" << ret->Dump() << "\n";
- EnsureNoBadReplaces(*ret, replaces);
- }
- return ret;
- }
- }
- TExprNode::TPtr TExprContext::ReplaceNode(TExprNode::TPtr&& start, const TExprNode& src, TExprNode::TPtr dst) {
- if (start->Type() == TExprNode::Lambda) {
- const auto& args = start->Head();
- auto body = GetLambdaBody(*start);
- std::optional<ui32> argIndex;
- for (ui32 index = 0U; index < args.ChildrenSize(); ++index) {
- const auto arg = args.Child(index);
- if (arg == &src) {
- if (argIndex) {
- ythrow yexception() << "argument is duplicated, #[" << arg->UniqueId() << "]";
- }
- argIndex = index;
- }
- }
- if (argIndex) {
- TExprNode::TListType newArgNodes;
- newArgNodes.reserve(args.ChildrenSize());
- TNodeOnNodeOwnedMap replaces(args.ChildrenSize());
- for (ui32 i = 0U; i < args.ChildrenSize(); ++i) {
- const auto arg = args.Child(i);
- auto newArg = (i == *argIndex) ? dst : ShallowCopy(*arg);
- YQL_ENSURE(replaces.emplace(arg, newArg).second);
- newArgNodes.emplace_back(std::move(newArg));
- }
- return NewLambda(start->Pos(), NewArguments(args.Pos(), std::move(newArgNodes)), ReplaceNodes<false>(std::move(body), replaces));
- }
- } else if (&src == start) {
- return dst;
- }
- return ReplaceNodes(std::move(start), {{&src, std::move(dst)}});
- }
- TExprNode::TPtr TExprContext::ReplaceNodes(TExprNode::TPtr&& start, const TNodeOnNodeOwnedMap& replaces) {
- TNodeOnNodeOwnedMap processed;
- return replaces.empty() ? std::move(start) : ReplaceNodesImpl<false>(std::move(start), replaces, processed, *this);
- }
- template<bool KeepTypeAnns>
- TExprNode::TListType TExprContext::ReplaceNodes(TExprNode::TListType&& starts, const TNodeOnNodeOwnedMap& replaces) {
- if (!replaces.empty()) {
- TNodeOnNodeOwnedMap processed;
- for (auto& node : starts) {
- node = ReplaceNodesImpl<KeepTypeAnns>(std::move(node), replaces, processed, *this);
- }
- }
- return std::move(starts);
- }
- template TExprNode::TListType TExprContext::ReplaceNodes<true>(TExprNode::TListType&& starts, const TNodeOnNodeOwnedMap& replaces);
- template TExprNode::TListType TExprContext::ReplaceNodes<false>(TExprNode::TListType&& starts, const TNodeOnNodeOwnedMap& replaces);
- bool IsDepended(const TExprNode& node, const TNodeSet& dependences) {
- TNodeSet visited;
- return !dependences.empty() && IsDependedImpl(node, dependences, visited);
- }
- void CheckArguments(const TExprNode& root) {
- try {
- TNodeMap<TNodeSetPtr> unresolvedArgsMap;
- TNodeSet allArgs;
- auto rootUnresolved = CollectUnresolvedArgs(root, unresolvedArgsMap, allArgs);
- if (rootUnresolved && !rootUnresolved->empty()) {
- TVector<ui64> ids;
- for (auto& i : *rootUnresolved) {
- ids.push_back(i->UniqueId());
- }
- ythrow yexception() << "detected unresolved arguments at top level: #[" << JoinSeq(", ", ids) << "]";
- }
- } catch (yexception& e) {
- e << "\n" << root.Dump();
- throw;
- }
- }
- TAstParseResult ConvertToAst(const TExprNode& root, TExprContext& exprContext, const TConvertToAstSettings& settings) {
- #ifdef _DEBUG
- CheckArguments(root);
- #endif
- TVisitNodeContext ctx(exprContext);
- ctx.RefAtoms = settings.RefAtoms;
- ctx.AllowFreeArgs = settings.AllowFreeArgs;
- ctx.NormalizeAtomFlags = settings.NormalizeAtomFlags;
- ctx.Pool = std::make_unique<TMemoryPool>(4096, TMemoryPool::TExpGrow::Instance(), settings.Allocator);
- ctx.Frames.push_back(TFrameContext());
- ctx.CurrentFrame = &ctx.Frames.front();
- VisitNode(root, 0ULL, ctx);
- ui32 uniqueNum = 0;
- for (auto& frame : ctx.Frames) {
- ctx.CurrentFrame = &frame;
- frame.TopoSortedNodes.reserve(frame.Nodes.size());
- for (const auto& node : frame.Nodes) {
- const auto name = ctx.FindBinding(node.second);
- if (name.empty()) {
- const auto& ref = ctx.References[node.second];
- if (!InlineNode(*node.second, ref.References, ref.Neighbors, settings)) {
- if (settings.PrintArguments && node.second->IsArgument()) {
- auto buffer = TStringBuilder() << "$" << ++uniqueNum
- << "{" << node.second->Content() << ":"
- << node.second->UniqueId() << "}";
- YQL_ENSURE(frame.Bindings.emplace(node.second, buffer).second);
- } else {
- char buffer[1 + 10 + 1];
- snprintf(buffer, sizeof(buffer), "$%" PRIu32, ++uniqueNum);
- YQL_ENSURE(frame.Bindings.emplace(node.second, buffer).second);
- }
- frame.TopoSortedNodes.emplace_back(node.second);
- }
- }
- }
- }
- ctx.CurrentFrame = &ctx.Frames.front();
- TAstParseResult result;
- result.Root = ConvertFunction(exprContext.AppendPosition(TPosition(1, 1)), {&root}, ctx, settings.AnnotationFlags, *ctx.Pool);
- result.Pool = std::move(ctx.Pool);
- return result;
- }
- TAstParseResult ConvertToAst(const TExprNode& root, TExprContext& exprContext, ui32 annotationFlags, bool refAtoms) {
- TConvertToAstSettings settings;
- settings.AnnotationFlags = annotationFlags;
- settings.RefAtoms = refAtoms;
- return ConvertToAst(root, exprContext, settings);
- }
- TString TExprNode::Dump() const {
- TNodeSet visited;
- TStringStream out;
- DumpNode(*this, out, 0, visited);
- return out.Str();
- }
- TPosition TExprNode::Pos(const TExprContext& ctx) const {
- return ctx.GetPosition(Pos());
- }
- TExprNode::TPtr TExprContext::RenameNode(const TExprNode& node, const TStringBuf& name) {
- const auto newNode = node.ChangeContent(AllocateNextUniqueId(), AppendString(name));
- ExprNodes.emplace_back(newNode.Get());
- return newNode;
- }
- TExprNode::TPtr TExprContext::ShallowCopy(const TExprNode& node) {
- YQL_ENSURE(node.Type() != TExprNode::Lambda);
- const auto newNode = node.Clone(AllocateNextUniqueId());
- ExprNodes.emplace_back(newNode.Get());
- return newNode;
- }
- TExprNode::TPtr TExprContext::ShallowCopyWithPosition(const TExprNode& node, TPositionHandle pos) {
- YQL_ENSURE(node.Type() != TExprNode::Lambda);
- const auto newNode = node.CloneWithPosition(AllocateNextUniqueId(), pos);
- ExprNodes.emplace_back(newNode.Get());
- return newNode;
- }
- TExprNode::TPtr TExprContext::ChangeChildren(const TExprNode& node, TExprNode::TListType&& children) {
- const auto newNode = node.ChangeChildren(AllocateNextUniqueId(), std::move(children));
- ExprNodes.emplace_back(newNode.Get());
- return newNode;
- }
- TExprNode::TPtr TExprContext::ChangeChild(const TExprNode& node, ui32 index, TExprNode::TPtr&& child) {
- const auto newNode = node.ChangeChild(AllocateNextUniqueId(), index, std::move(child));
- ExprNodes.emplace_back(newNode.Get());
- return newNode;
- }
- TExprNode::TPtr TExprContext::ExactChangeChildren(const TExprNode& node, TExprNode::TListType&& children) {
- const auto newNode = node.ChangeChildren(AllocateNextUniqueId(), std::move(children));
- newNode->SetTypeAnn(node.GetTypeAnn());
- newNode->CopyConstraints(node);
- newNode->SetState(node.GetState());
- newNode->Result = node.Result;
- ExprNodes.emplace_back(newNode.Get());
- return newNode;
- }
- TExprNode::TPtr TExprContext::ExactShallowCopy(const TExprNode& node) {
- YQL_ENSURE(node.Type() != TExprNode::Lambda);
- const auto newNode = node.Clone(AllocateNextUniqueId());
- newNode->SetTypeAnn(node.GetTypeAnn());
- newNode->CopyConstraints(node);
- newNode->SetState(node.GetState());
- newNode->Result = node.Result;
- ExprNodes.emplace_back(newNode.Get());
- return newNode;
- }
- TExprNode::TListType GetLambdaBody(const TExprNode& node) {
- switch (node.ChildrenSize()) {
- case 1U: return {};
- case 2U: return {node.TailPtr()};
- default: break;
- }
- auto body = node.ChildrenList();
- body.erase(body.cbegin());
- return body;
- }
- TExprNode::TPtr TExprContext::DeepCopyLambda(const TExprNode& node, TExprNode::TListType&& body) {
- YQL_ENSURE(node.IsLambda());
- const auto& prevArgs = node.Head();
- TNodeOnNodeOwnedMap replaces(prevArgs.ChildrenSize());
- TExprNode::TListType newArgNodes;
- newArgNodes.reserve(prevArgs.ChildrenSize());
- prevArgs.ForEachChild([&](const TExprNode& arg) {
- auto newArg = ShallowCopy(arg);
- YQL_ENSURE(replaces.emplace(&arg, newArg).second);
- newArgNodes.emplace_back(std::move(newArg));
- });
- auto newBody = ReplaceNodes(std::move(body), replaces);
- return NewLambda(node.Pos(), NewArguments(prevArgs.Pos(), std::move(newArgNodes)), std::move(newBody));
- }
- TExprNode::TPtr TExprContext::DeepCopyLambda(const TExprNode& node, TExprNode::TPtr&& body) {
- YQL_ENSURE(node.IsLambda());
- const auto& prevArgs = node.Head();
- TNodeOnNodeOwnedMap replaces(prevArgs.ChildrenSize());
- TExprNode::TListType newArgNodes;
- newArgNodes.reserve(prevArgs.ChildrenSize());
- prevArgs.ForEachChild([&](const TExprNode& arg) {
- auto newArg = ShallowCopy(arg);
- YQL_ENSURE(replaces.emplace(&arg, newArg).second);
- newArgNodes.emplace_back(std::move(newArg));
- });
- auto newBody = ReplaceNodes(body ? TExprNode::TListType{std::move(body)} : GetLambdaBody(node), replaces);
- return NewLambda(node.Pos(), NewArguments(prevArgs.Pos(), std::move(newArgNodes)), std::move(newBody));
- }
- TExprNode::TPtr TExprContext::FuseLambdas(const TExprNode& outer, const TExprNode& inner) {
- YQL_ENSURE(outer.IsLambda() && inner.IsLambda());
- const auto& outerArgs = outer.Head();
- const auto& innerArgs = inner.Head();
- TNodeOnNodeOwnedMap innerReplaces(innerArgs.ChildrenSize());
- TExprNode::TListType newArgNodes;
- newArgNodes.reserve(innerArgs.ChildrenSize());
- innerArgs.ForEachChild([&](const TExprNode& arg) {
- auto newArg = ShallowCopy(arg);
- YQL_ENSURE(innerReplaces.emplace(&arg, newArg).second);
- newArgNodes.emplace_back(std::move(newArg));
- });
- auto body = ReplaceNodes(GetLambdaBody(inner), innerReplaces);
- TExprNode::TListType newBody;
- auto outerBody = GetLambdaBody(outer);
- if (outerArgs.ChildrenSize() + 1U == inner.ChildrenSize()) {
- auto i = 0U;
- TNodeOnNodeOwnedMap outerReplaces(outerArgs.ChildrenSize());
- outerArgs.ForEachChild([&](const TExprNode& arg) {
- YQL_ENSURE(outerReplaces.emplace(&arg, std::move(body[i++])).second);
- });
- newBody = ReplaceNodes(std::move(outerBody), outerReplaces);
- } else if (1U == outerArgs.ChildrenSize()) {
- newBody.reserve(newBody.size() * body.size());
- for (auto item : body) {
- for (auto root : outerBody) {
- newBody.emplace_back(ReplaceNode(TExprNode::TPtr(root), outerArgs.Head(), TExprNode::TPtr(item)));
- }
- }
- } else {
- YQL_ENSURE(outerBody.empty(), "Incompatible lambdas for fuse.");
- }
- return NewLambda(outer.Pos(), NewArguments(inner.Head().Pos(), std::move(newArgNodes)), std::move(newBody));
- }
- TExprNode::TPtr TExprContext::DeepCopy(const TExprNode& node, TExprContext& nodeCtx, TNodeOnNodeOwnedMap& deepClones,
- bool internStrings, bool copyTypes, bool copyResult, TCustomDeepCopier customCopier)
- {
- const auto ins = deepClones.emplace(&node, nullptr);
- if (ins.second) {
- TExprNode::TListType children;
- children.reserve(node.ChildrenSize());
- if (customCopier && customCopier(node, children)) {
- } else {
- node.ForEachChild([&](const TExprNode& child) {
- children.emplace_back(DeepCopy(child, nodeCtx, deepClones, internStrings, copyTypes, copyResult, customCopier));
- });
- }
- ++NodeAllocationCounter;
- auto newNode = TExprNode::NewNode(AppendPosition(nodeCtx.GetPosition(node.Pos())), node.Type(),
- std::move(children), internStrings ? AppendString(node.Content()) : node.Content(), node.Flags(),
- AllocateNextUniqueId());
- if (copyTypes && node.GetTypeAnn()) {
- newNode->SetTypeAnn(node.GetTypeAnn());
- }
- if (copyResult && node.IsCallable() && node.HasResult()) {
- newNode->SetResult(nodeCtx.ShallowCopy(node.GetResult()));
- }
- ins.first->second = newNode;
- ExprNodes.emplace_back(ins.first->second.Get());
- }
- return ins.first->second;
- }
- TExprNode::TPtr TExprContext::WrapByCallableIf(bool condition, const TStringBuf& callable, TExprNode::TPtr&& node) {
- if (!condition) {
- return node;
- }
- const auto pos = node->Pos();
- return NewCallable(pos, callable, {std::move(node)});
- }
- TExprNode::TPtr TExprContext::SwapWithHead(const TExprNode& node) {
- return ChangeChild(node.Head(), 0U, ChangeChild(node, 0U, node.Head().HeadPtr()));
- }
- TConstraintSet TExprContext::MakeConstraintSet(const NYT::TNode& serializedConstraints) {
- const static std::unordered_map<std::string_view, std::function<const TConstraintNode*(TExprContext&, const NYT::TNode&)>> FACTORIES = {
- {TSortedConstraintNode::Name(), std::mem_fn(&TExprContext::MakeConstraint<TSortedConstraintNode, const NYT::TNode&>)},
- {TChoppedConstraintNode::Name(), std::mem_fn(&TExprContext::MakeConstraint<TChoppedConstraintNode, const NYT::TNode&>)},
- {TUniqueConstraintNode::Name(), std::mem_fn(&TExprContext::MakeConstraint<TUniqueConstraintNode, const NYT::TNode&>)},
- {TDistinctConstraintNode::Name(), std::mem_fn(&TExprContext::MakeConstraint<TDistinctConstraintNode, const NYT::TNode&>)},
- {TEmptyConstraintNode::Name(), std::mem_fn(&TExprContext::MakeConstraint<TEmptyConstraintNode, const NYT::TNode&>)},
- {TVarIndexConstraintNode::Name(), std::mem_fn(&TExprContext::MakeConstraint<TVarIndexConstraintNode, const NYT::TNode&>)},
- {TMultiConstraintNode::Name(), std::mem_fn(&TExprContext::MakeConstraint<TMultiConstraintNode, const NYT::TNode&>)},
- };
- TConstraintSet res;
- YQL_ENSURE(serializedConstraints.IsMap(), "Unexpected node type with serialize constraints: " << serializedConstraints.GetType());
- for (const auto& [key, node]: serializedConstraints.AsMap()) {
- auto it = FACTORIES.find(key);
- YQL_ENSURE(it != FACTORIES.cend(), "Unsupported constraint construction: " << key);
- try {
- res.AddConstraint((it->second)(*this, node));
- } catch (...) {
- YQL_ENSURE(false, "Error while constructing constraint: " << CurrentExceptionMessage());
- }
- }
- return res;
- }
- TNodeException::TNodeException()
- : Pos_()
- {
- }
- TNodeException::TNodeException(const TExprNode& node)
- : Pos_(node.Pos())
- {
- }
- TNodeException::TNodeException(const TExprNode* node)
- : Pos_(node ? node->Pos() : TPositionHandle())
- {
- }
- TNodeException::TNodeException(const TPositionHandle& pos)
- : Pos_(pos)
- {
- }
- bool ValidateName(TPosition position, TStringBuf name, TStringBuf descr, TExprContext& ctx) {
- if (name.empty()) {
- ctx.AddError(TIssue(position,
- TStringBuilder() << "Empty " << descr << " name is not allowed"));
- return false;
- }
- if (!IsUtf8(name)) {
- ctx.AddError(TIssue(position, TStringBuilder() <<
- TString(descr).to_title() << " name must be a valid utf-8 byte sequence: " << TString{name}.Quote()));
- return false;
- }
- if (name.size() > 16_KB) {
- ctx.AddError(TIssue(position, TStringBuilder() <<
- TString(descr).to_title() << " name length must be less than " << 16_KB));
- return false;
- }
- return true;
- }
- bool ValidateName(TPositionHandle position, TStringBuf name, TStringBuf descr, TExprContext& ctx) {
- return ValidateName(ctx.GetPosition(position), name, descr, ctx);
- }
- bool TDataExprParamsType::Validate(TPosition position, TExprContext& ctx) const {
- if (GetSlot() != EDataSlot::Decimal) {
- ctx.AddError(TIssue(position, TStringBuilder() << "Only Decimal may contain parameters, but got: " << GetName()));
- return false;
- }
- ui8 precision;
- if (!TryFromString<ui8>(GetParamOne(), precision)){
- ctx.AddError(TIssue(position, TStringBuilder() << "Invalid decimal precision: " << GetParamOne()));
- return false;
- }
- if (!precision || precision > 35) {
- ctx.AddError(TIssue(position, TStringBuilder() << "Invalid decimal precision: " << GetParamOne()));
- return false;
- }
- ui8 scale;
- if (!TryFromString<ui8>(GetParamTwo(), scale)){
- ctx.AddError(TIssue(position, TStringBuilder() << "Invalid decimal scale: " << GetParamTwo()));
- return false;
- }
- if (scale > precision) {
- ctx.AddError(TIssue(position, TStringBuilder() << "Invalid decimal parameters: (" << GetParamOne() << "," << GetParamTwo() << ")."));
- return false;
- }
- return true;
- }
- bool TDataExprParamsType::Validate(TPositionHandle position, TExprContext& ctx) const {
- return Validate(ctx.GetPosition(position), ctx);
- }
- bool TItemExprType::Validate(TPosition position, TExprContext& ctx) const {
- return ValidateName(position, Name, "member", ctx);
- }
- bool TItemExprType::Validate(TPositionHandle position, TExprContext& ctx) const {
- return Validate(ctx.GetPosition(position), ctx);
- }
- TStringBuf TItemExprType::GetCleanName(bool isVirtual) const {
- if (!isVirtual) {
- return Name;
- }
- YQL_ENSURE(Name.StartsWith(YqlVirtualPrefix));
- return Name.SubStr(YqlVirtualPrefix.size());
- }
- const TItemExprType* TItemExprType::GetCleanItem(bool isVirtual, TExprContext& ctx) const {
- if (!isVirtual) {
- return this;
- }
- YQL_ENSURE(Name.StartsWith(YqlVirtualPrefix));
- return ctx.MakeType<TItemExprType>(Name.SubStr(YqlVirtualPrefix.size()), ItemType);
- }
- bool TMultiExprType::Validate(TPosition position, TExprContext& ctx) const {
- if (Items.size() > Max<ui16>()) {
- ctx.AddError(TIssue(position, TStringBuilder() << "Too many elements: " << Items.size()));
- return false;
- }
- return true;
- }
- bool TMultiExprType::Validate(TPositionHandle position, TExprContext& ctx) const {
- return Validate(ctx.GetPosition(position), ctx);
- }
- bool TTupleExprType::Validate(TPosition position, TExprContext& ctx) const {
- if (Items.size() > Max<ui16>()) {
- ctx.AddError(TIssue(position, TStringBuilder() << "Too many tuple elements: " << Items.size()));
- return false;
- }
- return true;
- }
- bool TTupleExprType::Validate(TPositionHandle position, TExprContext& ctx) const {
- return Validate(ctx.GetPosition(position), ctx);
- }
- bool TStructExprType::Validate(TPosition position, TExprContext& ctx) const {
- if (Items.size() > Max<ui16>()) {
- ctx.AddError(TIssue(position, TStringBuilder() << "Too many struct members: " << Items.size()));
- return false;
- }
- TString lastName;
- for (auto& item : Items) {
- if (!item->Validate(position, ctx)) {
- return false;
- }
- if (item->GetName() == lastName) {
- ctx.AddError(TIssue(position, TStringBuilder() << "Duplicated member: " << lastName));
- return false;
- }
- lastName = item->GetName();
- }
- return true;
- }
- bool TStructExprType::Validate(TPositionHandle position, TExprContext& ctx) const {
- return Validate(ctx.GetPosition(position), ctx);
- }
- bool TVariantExprType::Validate(TPosition position, TExprContext& ctx) const {
- if (UnderlyingType->GetKind() == ETypeAnnotationKind::Tuple) {
- if (!UnderlyingType->Cast<TTupleExprType>()->GetSize()) {
- ctx.AddError(TIssue(position, TStringBuilder() << "Empty tuple is not allowed as underlying type"));
- return false;
- }
- }
- else if (UnderlyingType->GetKind() == ETypeAnnotationKind::Struct) {
- if (!UnderlyingType->Cast<TStructExprType>()->GetSize()) {
- ctx.AddError(TIssue(position, TStringBuilder() << "Empty struct is not allowed as underlying type"));
- return false;
- }
- }
- else {
- ctx.AddError(TIssue(position, TStringBuilder() << "Expected tuple or struct, but got:" << *UnderlyingType));
- return false;
- }
- return true;
- }
- bool TVariantExprType::Validate(TPositionHandle position, TExprContext& ctx) const {
- return Validate(ctx.GetPosition(position), ctx);
- }
- ui32 TVariantExprType::MakeFlags(const TTypeAnnotationNode* underlyingType) {
- switch (underlyingType->GetKind()) {
- case ETypeAnnotationKind::Tuple: {
- const auto tupleType = underlyingType->Cast<TTupleExprType>();
- auto ret = CombineFlags(tupleType->GetItems());
- if (tupleType->GetSize() > 1) {
- ret |= TypeHasManyValues;
- }
- return ret;
- }
- case ETypeAnnotationKind::Struct: {
- const auto structType = underlyingType->Cast<TStructExprType>();
- auto ret = CombineFlags(structType->GetItems());
- if (structType->GetSize() > 1) {
- ret |= TypeHasManyValues;
- }
- return ret;
- }
- default: break;
- }
- ythrow yexception() << "unexpected underlying type" << *underlyingType;
- }
- bool TDictExprType::Validate(TPosition position, TExprContext& ctx) const {
- if (KeyType->IsHashable() && KeyType->IsEquatable()) {
- return true;
- }
- if (KeyType->IsComparableInternal()) {
- return true;
- }
- ctx.AddError(TIssue(position, TStringBuilder() << "Expected hashable and equatable or internally comparable dict key type, but got: " << *KeyType));
- return false;
- }
- bool TDictExprType::Validate(TPositionHandle position, TExprContext& ctx) const {
- return Validate(ctx.GetPosition(position), ctx);
- }
- bool TCallableExprType::Validate(TPosition position, TExprContext& ctx) const {
- if (OptionalArgumentsCount > Arguments.size()) {
- ctx.AddError(TIssue(position, TStringBuilder() << "Too many optional arguments: " << OptionalArgumentsCount
- << ", function has only " << Arguments.size() << " arguments"));
- return false;
- }
- for (ui32 index = Arguments.size() - OptionalArgumentsCount; index < Arguments.size(); ++index) {
- auto type = Arguments[index].Type;
- if (type->GetKind() != ETypeAnnotationKind::Optional) {
- ctx.AddError(TIssue(position, TStringBuilder() << "Expected optional type for argument: " << (index + 1)
- << " because it's an optional argument, but got: " << *type));
- return false;
- }
- }
- bool startedNames = false;
- std::unordered_set<std::string_view> usedNames(Arguments.size());
- for (ui32 index = 0; index < Arguments.size(); ++index) {
- bool hasName = !Arguments[index].Name.empty();
- if (startedNames) {
- if (!hasName) {
- ctx.AddError(TIssue(position, TStringBuilder() << "Unexpected positional argument at position "
- << (index + 1) << " just after named arguments"));
- return false;
- }
- } else {
- startedNames = hasName;
- }
- if (hasName) {
- if (!usedNames.insert(Arguments[index].Name).second) {
- ctx.AddError(TIssue(position, TStringBuilder() << "Duplication of named argument: " << Arguments[index].Name));
- return false;
- }
- }
- }
- return true;
- }
- bool TCallableExprType::Validate(TPositionHandle position, TExprContext& ctx) const {
- return Validate(ctx.GetPosition(position), ctx);
- }
- bool TTaggedExprType::Validate(TPosition position, TExprContext& ctx) const {
- return ValidateName(position, Tag, "tag", ctx);
- }
- bool TTaggedExprType::Validate(TPositionHandle position, TExprContext& ctx) const {
- return Validate(ctx.GetPosition(position), ctx);
- }
- const TString& TPgExprType::GetName() const {
- return NPg::LookupType(TypeId).Name;
- }
- ui32 TPgExprType::GetFlags(ui32 typeId) {
- auto descPtr = &NPg::LookupType(typeId);
- if (descPtr->ArrayTypeId == descPtr->TypeId) {
- auto elemType = descPtr->ElementTypeId;
- descPtr = &NPg::LookupType(elemType);
- }
- const auto& desc = *descPtr;
- ui32 ret = TypeHasManyValues | TypeHasOptional;
- if ((!desc.SendFuncId || !desc.ReceiveFuncId) && (!desc.OutFuncId || !desc.InFuncId)) {
- ret |= TypeNonPersistable;
- }
- if (!desc.LessProcId || !desc.CompareProcId) {
- ret |= TypeNonComparable;
- }
- if (!desc.EqualProcId || !desc.CompareProcId) {
- if (desc.TypeId != NPg::UnknownOid) {
- ret |= TypeNonEquatable;
- }
- }
- if (!desc.HashProcId) {
- ret |= TypeNonHashable;
- }
- static const std::unordered_set<std::string_view> PgSupportedPresort = {
- "bool"sv,
- "int2"sv,
- "int4"sv,
- "int8"sv,
- "float4"sv,
- "float8"sv,
- "bytea"sv,
- "varchar"sv,
- "text"sv,
- "cstring"sv
- };
- if (!PgSupportedPresort.contains(descPtr->Name)) {
- ret |= TypeNonPresortable;
- }
- return ret;
- }
- ui64 TPgExprType::GetPgExtensionsMask(ui32 typeId) {
- auto descPtr = &NPg::LookupType(typeId);
- return MakePgExtensionMask(descPtr->ExtensionIndex);
- }
- ui64 MakePgExtensionMask(ui32 extensionIndex) {
- if (!extensionIndex) {
- return 0;
- }
- YQL_ENSURE(extensionIndex <= 64);
- return 1ull << (extensionIndex - 1);
- }
- TExprContext::TExprContext(ui64 nextUniqueId)
- : StringPool(4096)
- , NextUniqueId(nextUniqueId)
- , Frozen(false)
- , PositionSet(
- 16,
- [this](TPositionHandle p) { return GetHash(p); },
- [this](TPositionHandle a, TPositionHandle b) { return IsEqual(a, b); }
- )
- {
- auto handle = AppendPosition(TPosition());
- YQL_ENSURE(handle.Handle == 0);
- IssueManager.SetWarningToErrorTreatMessage(
- "Treat warning as error mode enabled. "
- "To disable it use \"pragma warning(\"default\", <code>);\"");
- IssueManager.SetIssueCountLimit(100);
- }
- TPositionHandle TExprContext::AppendPosition(const TPosition& pos) {
- YQL_ENSURE(Positions.size() <= Max<ui32>(), "Too many positions");
- TPositionHandle handle;
- handle.Handle = (ui32)Positions.size();
- Positions.push_back(pos);
- auto inserted = PositionSet.insert(handle);
- if (inserted.second) {
- return handle;
- }
- Positions.pop_back();
- return *inserted.first;
- }
- TPosition TExprContext::GetPosition(TPositionHandle handle) const {
- YQL_ENSURE(handle.Handle < Positions.size(), "Unknown PositionHandle");
- return Positions[handle.Handle];
- }
- TExprContext::~TExprContext() {
- UnFreeze();
- }
- void TExprContext::Freeze() {
- for (auto& node : ExprNodes) {
- node->MarkFrozen();
- }
- Frozen = true;
- }
- void TExprContext::UnFreeze() {
- if (Frozen) {
- for (auto& node : ExprNodes) {
- node->MarkFrozen(false);
- }
- Frozen = false;
- }
- }
- void TExprContext::Reset() {
- YQL_ENSURE(!Frozen);
- IssueManager.Reset();
- Step.Reset();
- RepeatTransformCounter = 0;
- }
- bool TExprContext::IsEqual(TPositionHandle a, TPositionHandle b) const {
- YQL_ENSURE(a.Handle < Positions.size());
- YQL_ENSURE(b.Handle < Positions.size());
- return Positions[a.Handle] == Positions[b.Handle];
- }
- size_t TExprContext::GetHash(TPositionHandle p) const {
- YQL_ENSURE(p.Handle < Positions.size());
- const TPosition& pos = Positions[p.Handle];
- size_t h = ComputeHash(pos.File);
- h = CombineHashes(h, NumericHash(pos.Row));
- return CombineHashes(h, NumericHash(pos.Column));
- }
- std::string_view TExprContext::GetIndexAsString(ui32 index) {
- const auto it = Indexes.find(index);
- if (it != Indexes.cend()) {
- return it->second;
- }
- const auto& newBuf = AppendString(ToString(index));
- Indexes.emplace_hint(it, index, newBuf);
- return newBuf;
- }
- template<class T, typename... Args>
- const T* MakeSinglethonType(TExprContext& ctx, Args&&... args) {
- auto& singleton = std::get<const T*>(ctx.SingletonTypeCache);
- if (!singleton)
- singleton = AddType<T>(ctx, T::MakeHash(args...), std::forward<Args>(args)...);
- return singleton;
- }
- const TVoidExprType* TMakeTypeImpl<TVoidExprType>::Make(TExprContext& ctx) {
- return MakeSinglethonType<TVoidExprType>(ctx);
- }
- const TNullExprType* TMakeTypeImpl<TNullExprType>::Make(TExprContext& ctx) {
- return MakeSinglethonType<TNullExprType>(ctx);
- }
- const TEmptyListExprType* TMakeTypeImpl<TEmptyListExprType>::Make(TExprContext& ctx) {
- return MakeSinglethonType<TEmptyListExprType>(ctx);
- }
- const TEmptyDictExprType* TMakeTypeImpl<TEmptyDictExprType>::Make(TExprContext& ctx) {
- return MakeSinglethonType<TEmptyDictExprType>(ctx);
- }
- const TUnitExprType* TMakeTypeImpl<TUnitExprType>::Make(TExprContext& ctx) {
- return MakeSinglethonType<TUnitExprType>(ctx);
- }
- const TWorldExprType* TMakeTypeImpl<TWorldExprType>::Make(TExprContext& ctx) {
- return MakeSinglethonType<TWorldExprType>(ctx);
- }
- const TGenericExprType* TMakeTypeImpl<TGenericExprType>::Make(TExprContext& ctx) {
- return MakeSinglethonType<TGenericExprType>(ctx);
- }
- const TItemExprType* TMakeTypeImpl<TItemExprType>::Make(TExprContext& ctx, const TStringBuf& name, const TTypeAnnotationNode* itemType) {
- const auto hash = TItemExprType::MakeHash(name, itemType);
- TItemExprType sample(hash, name, itemType);
- if (const auto found = FindType(sample, ctx))
- return found;
- auto nameStr = ctx.AppendString(name);
- return AddType<TItemExprType>(ctx, hash, nameStr, itemType);
- }
- const TListExprType* TMakeTypeImpl<TListExprType>::Make(TExprContext& ctx, const TTypeAnnotationNode* itemType) {
- const auto hash = TListExprType::MakeHash(itemType);
- TListExprType sample(hash, itemType);
- if (const auto found = FindType(sample, ctx))
- return found;
- return AddType<TListExprType>(ctx, hash, itemType);
- }
- const TOptionalExprType* TMakeTypeImpl<TOptionalExprType>::Make(TExprContext& ctx, const TTypeAnnotationNode* itemType) {
- const auto hash = TOptionalExprType::MakeHash(itemType);
- TOptionalExprType sample(hash, itemType);
- if (const auto found = FindType(sample, ctx))
- return found;
- return AddType<TOptionalExprType>(ctx, hash, itemType);
- }
- const TVariantExprType* TMakeTypeImpl<TVariantExprType>::Make(TExprContext& ctx, const TTypeAnnotationNode* underlyingType) {
- const auto hash = TVariantExprType::MakeHash(underlyingType);
- TVariantExprType sample(hash, underlyingType);
- if (const auto found = FindType(sample, ctx))
- return found;
- return AddType<TVariantExprType>(ctx, hash, underlyingType);
- }
- const TErrorExprType* TMakeTypeImpl<TErrorExprType>::Make(TExprContext& ctx, const TIssue& error) {
- const auto hash = TErrorExprType::MakeHash(error);
- TErrorExprType sample(hash, error);
- if (const auto found = FindType(sample, ctx))
- return found;
- return AddType<TErrorExprType>(ctx, hash, error);
- }
- const TDictExprType* TMakeTypeImpl<TDictExprType>::Make(TExprContext& ctx, const TTypeAnnotationNode* keyType,
- const TTypeAnnotationNode* payloadType) {
- const auto hash = TDictExprType::MakeHash(keyType, payloadType);
- TDictExprType sample(hash, keyType, payloadType);
- if (const auto found = FindType(sample, ctx))
- return found;
- return AddType<TDictExprType>(ctx, hash, keyType, payloadType);
- }
- const TTypeExprType* TMakeTypeImpl<TTypeExprType>::Make(TExprContext& ctx, const TTypeAnnotationNode* baseType) {
- const auto hash = TTypeExprType::MakeHash(baseType);
- TTypeExprType sample(hash, baseType);
- if (const auto found = FindType(sample, ctx))
- return found;
- return AddType<TTypeExprType>(ctx, hash, baseType);
- }
- const TDataExprType* TMakeTypeImpl<TDataExprType>::Make(TExprContext& ctx, EDataSlot slot) {
- const auto hash = TDataExprType::MakeHash(slot);
- TDataExprType sample(hash, slot);
- if (const auto found = FindType(sample, ctx))
- return found;
- return AddType<TDataExprType>(ctx, hash, slot);
- }
- const TPgExprType* TMakeTypeImpl<TPgExprType>::Make(TExprContext& ctx, ui32 typeId) {
- const auto hash = TPgExprType::MakeHash(typeId);
- TPgExprType sample(hash, typeId);
- if (const auto found = FindType(sample, ctx))
- return found;
- return AddType<TPgExprType>(ctx, hash, typeId);
- }
- const TDataExprParamsType* TMakeTypeImpl<TDataExprParamsType>::Make(TExprContext& ctx, EDataSlot slot, const TStringBuf& one, const TStringBuf& two) {
- const auto hash = TDataExprParamsType::MakeHash(slot, one, two);
- TDataExprParamsType sample(hash, slot, one, two);
- if (const auto found = FindType(sample, ctx))
- return found;
- return AddType<TDataExprParamsType>(ctx, hash, slot, ctx.AppendString(one), ctx.AppendString(two));
- }
- const TCallableExprType* TMakeTypeImpl<TCallableExprType>::Make(
- TExprContext& ctx, const TTypeAnnotationNode* returnType, const TVector<TCallableExprType::TArgumentInfo>& arguments,
- size_t optionalArgumentsCount, const TStringBuf& payload) {
- const auto hash = TCallableExprType::MakeHash(returnType, arguments, optionalArgumentsCount, payload);
- TCallableExprType sample(hash, returnType, arguments, optionalArgumentsCount, payload);
- if (const auto found = FindType(sample, ctx))
- return found;
- TVector<TCallableExprType::TArgumentInfo> newArgs;
- newArgs.reserve(arguments.size());
- for (const auto& x : arguments) {
- TCallableExprType::TArgumentInfo arg;
- arg.Type = x.Type;
- arg.Name = ctx.AppendString(x.Name);
- arg.Flags = x.Flags;
- newArgs.emplace_back(arg);
- }
- return AddType<TCallableExprType>(ctx, hash, returnType, newArgs, optionalArgumentsCount, ctx.AppendString(payload));
- }
- const TResourceExprType* TMakeTypeImpl<TResourceExprType>::Make(TExprContext& ctx, const TStringBuf& tag) {
- const auto hash = TResourceExprType::MakeHash(tag);
- TResourceExprType sample(hash, tag);
- if (const auto found = FindType(sample, ctx))
- return found;
- return AddType<TResourceExprType>(ctx, hash, ctx.AppendString(tag));
- }
- const TTaggedExprType* TMakeTypeImpl<TTaggedExprType>::Make(
- TExprContext& ctx, const TTypeAnnotationNode* baseType, const TStringBuf& tag) {
- const auto hash = TTaggedExprType::MakeHash(baseType, tag);
- TTaggedExprType sample(hash, baseType, tag);
- if (const auto found = FindType(sample, ctx))
- return found;
- return AddType<TTaggedExprType>(ctx, hash, baseType, ctx.AppendString(tag));
- }
- const TStructExprType* TMakeTypeImpl<TStructExprType>::Make(
- TExprContext& ctx, const TVector<const TItemExprType*>& items) {
- if (items.empty())
- return MakeSinglethonType<TStructExprType>(ctx, items);
- auto sortedItems = items;
- Sort(sortedItems, TStructExprType::TItemLess());
- const auto hash = TStructExprType::MakeHash(sortedItems);
- TStructExprType sample(hash, sortedItems);
- if (const auto found = FindType(sample, ctx))
- return found;
- return AddType<TStructExprType>(ctx, hash, sortedItems);
- }
- const TMultiExprType* TMakeTypeImpl<TMultiExprType>::Make(TExprContext& ctx, const TTypeAnnotationNode::TListType& items) {
- if (items.empty())
- return MakeSinglethonType<TMultiExprType>(ctx, items);
- const auto hash = TMultiExprType::MakeHash(items);
- TMultiExprType sample(hash, items);
- if (const auto found = FindType(sample, ctx))
- return found;
- return AddType<TMultiExprType>(ctx, hash, items);
- }
- const TTupleExprType* TMakeTypeImpl<TTupleExprType>::Make(TExprContext& ctx, const TTypeAnnotationNode::TListType& items) {
- if (items.empty())
- return MakeSinglethonType<TTupleExprType>(ctx, items);
- const auto hash = TTupleExprType::MakeHash(items);
- TTupleExprType sample(hash, items);
- if (const auto found = FindType(sample, ctx))
- return found;
- return AddType<TTupleExprType>(ctx, hash, items);
- }
- const TStreamExprType* TMakeTypeImpl<TStreamExprType>::Make(TExprContext& ctx, const TTypeAnnotationNode* itemType) {
- const auto hash = TStreamExprType::MakeHash(itemType);
- TStreamExprType sample(hash, itemType);
- if (const auto found = FindType(sample, ctx))
- return found;
- return AddType<TStreamExprType>(ctx, hash, itemType);
- }
- const TFlowExprType* TMakeTypeImpl<TFlowExprType>::Make(TExprContext& ctx, const TTypeAnnotationNode* itemType) {
- const auto hash = TFlowExprType::MakeHash(itemType);
- TFlowExprType sample(hash, itemType);
- if (const auto found = FindType(sample, ctx))
- return found;
- return AddType<TFlowExprType>(ctx, hash, itemType);
- }
- const TBlockExprType* TMakeTypeImpl<TBlockExprType>::Make(TExprContext& ctx, const TTypeAnnotationNode* itemType) {
- const auto hash = TBlockExprType::MakeHash(itemType);
- TBlockExprType sample(hash, itemType);
- if (const auto found = FindType(sample, ctx))
- return found;
- return AddType<TBlockExprType>(ctx, hash, itemType);
- }
- const TScalarExprType* TMakeTypeImpl<TScalarExprType>::Make(TExprContext& ctx, const TTypeAnnotationNode* itemType) {
- const auto hash = TScalarExprType::MakeHash(itemType);
- TScalarExprType sample(hash, itemType);
- if (const auto found = FindType(sample, ctx))
- return found;
- return AddType<TScalarExprType>(ctx, hash, itemType);
- }
- bool CompareExprTrees(const TExprNode*& one, const TExprNode*& two) {
- TArgumentsMap map;
- ui32 level = 0;
- TNodesPairSet visited;
- return CompareExpressions(one, two, map, level, visited);
- }
- bool CompareExprTreeParts(const TExprNode& one, const TExprNode& two, const TNodeMap<ui32>& argsMap) {
- TArgumentsMap map;
- ui32 level = 0;
- TNodesPairSet visited;
- map.reserve(argsMap.size());
- std::for_each(argsMap.cbegin(), argsMap.cend(), [&](const TNodeMap<ui32>::value_type& v){ map.emplace(v.first, std::make_pair(0U, v.second)); });
- auto l = &one, r = &two;
- return CompareExpressions(l, r, map, level, visited);
- }
- class TCacheKeyBuilder {
- public:
- TString Process(const TExprNode& root) {
- SHA256_Init(&Sha);
- unsigned char hash[SHA256_DIGEST_LENGTH];
- Visit(root);
- SHA256_Final(hash, &Sha);
- return TString((const char*)hash, sizeof(hash));
- }
- private:
- void Visit(const TExprNode& node) {
- auto [it, inserted] = Visited.emplace(&node, Visited.size());
- SHA256_Update(&Sha, &it->second, sizeof(it->second));
- if (!inserted) {
- return;
- }
- ui32 type = node.Type();
- SHA256_Update(&Sha, &type, sizeof(type));
- if (node.Type() == TExprNode::EType::Atom || node.Type() == TExprNode::EType::Callable) {
- ui32 textLen = node.Content().size();
- SHA256_Update(&Sha, &textLen, sizeof(textLen));
- SHA256_Update(&Sha, node.Content().data(), textLen);
- }
- if (node.Type() == TExprNode::EType::Atom || node.Type() == TExprNode::EType::Argument || node.Type() == TExprNode::EType::World) {
- return;
- }
- ui32 len = node.ChildrenSize();
- SHA256_Update(&Sha, &len, sizeof(len));
- for (const auto& child : node.Children()) {
- Visit(*child);
- }
- }
- private:
- SHA256_CTX Sha;
- TNodeMap<ui64> Visited;
- };
- TString MakeCacheKey(const TExprNode& root) {
- TCacheKeyBuilder builder;
- return builder.Process(root);
- }
- void GatherParents(const TExprNode& node, TParentsMap& parentsMap) {
- parentsMap.clear();
- TNodeSet visisted;
- GatherParentsImpl(node, parentsMap, visisted);
- }
- void CheckCounts(const TExprNode& root) {
- TRefCountsMap refCounts;
- CalculateReferences(root, refCounts);
- TNodeSet visited;
- CheckReferences(root, refCounts, visited);
- }
- TString SubstParameters(const TString& str, const TMaybe<NYT::TNode>& params, TSet<TString>* usedNames) {
- size_t pos = 0;
- try {
- TStringBuilder res;
- bool insideBrackets = false;
- TStringBuilder paramBuilder;
- for (char c : str) {
- if (c == '{') {
- if (insideBrackets) {
- throw yexception() << "Unpexpected {";
- }
- insideBrackets = true;
- continue;
- }
- if (c == '}') {
- if (!insideBrackets) {
- throw yexception() << "Unexpected }";
- }
- insideBrackets = false;
- TString param = paramBuilder;
- paramBuilder.clear();
- if (usedNames) {
- usedNames->insert(param);
- }
- if (params) {
- const auto& map = params->AsMap();
- auto it = map.find(param);
- if (it == map.end()) {
- throw yexception() << "No such parameter: '" << param << "'";
- }
- const auto& value = it->second["Data"];
- if (!value.IsString()) {
- throw yexception() << "Parameter value must be a string";
- }
- res << value.AsString();
- }
- continue;
- }
- if (insideBrackets) {
- paramBuilder << c;
- }
- else {
- res << c;
- }
- ++pos;
- }
- if (insideBrackets) {
- throw yexception() << "Missing }";
- }
- return res;
- }
- catch (yexception& e) {
- throw yexception() << "Failed to substitute parameters into url: " << str << ", reason:" << e.what() << ", position: " << pos;
- }
- }
- const TTypeAnnotationNode* GetSeqItemType(const TTypeAnnotationNode* type) {
- if (!type)
- return nullptr;
- switch (type->GetKind()) {
- case ETypeAnnotationKind::List: return type->Cast<TListExprType>()->GetItemType();
- case ETypeAnnotationKind::Flow: return type->Cast<TFlowExprType>()->GetItemType();
- case ETypeAnnotationKind::Stream: return type->Cast<TStreamExprType>()->GetItemType();
- case ETypeAnnotationKind::Optional: return type->Cast<TOptionalExprType>()->GetItemType();
- default: break;
- }
- return nullptr;
- }
- const TTypeAnnotationNode& GetSeqItemType(const TTypeAnnotationNode& type) {
- if (const auto itemType = GetSeqItemType(&type))
- return *itemType;
- throw yexception() << "Impossible to get item type from " << type;
- }
- const TTypeAnnotationNode& RemoveOptionality(const TTypeAnnotationNode& type) {
- return ETypeAnnotationKind::Optional == type.GetKind() ? *type.Cast<TOptionalExprType>()->GetItemType() : type;
- }
- TMaybe<TIssue> NormalizeName(TPosition position, TString& name) {
- const ui32 inputLength = name.length();
- ui32 startCharPos = 0;
- ui32 totalSkipped = 0;
- bool atStart = true;
- bool justSkippedUnderscore = false;
- for (ui32 i = 0; i < inputLength; ++i) {
- const char c = name.at(i);
- if (c == '_') {
- if (!atStart) {
- if (justSkippedUnderscore) {
- return TIssue(position, TStringBuilder() << "\"" << name << "\" looks weird, has multiple consecutive underscores");
- }
- justSkippedUnderscore = true;
- ++totalSkipped;
- continue;
- } else {
- ++startCharPos;
- }
- }
- else {
- atStart = false;
- justSkippedUnderscore = false;
- }
- }
- if (totalSkipped >= 5) {
- return TIssue(position, TStringBuilder() << "\"" << name << "\" looks weird, has multiple consecutive underscores");
- }
- ui32 outPos = startCharPos;
- for (ui32 i = startCharPos; i < inputLength; i++) {
- const char c = name.at(i);
- if (c == '_') {
- continue;
- } else {
- name[outPos] = AsciiToLower(c);
- ++outPos;
- }
- }
- name.resize(outPos);
- Y_ABORT_UNLESS(inputLength - outPos == totalSkipped);
- return Nothing();
- }
- TString NormalizeName(const TStringBuf& name) {
- TString result(name);
- TMaybe<TIssue> error = NormalizeName(TPosition(), result);
- YQL_ENSURE(error.Empty(), "" << error->GetMessage());
- return result;
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TUnitExprType& type) {
- Y_UNUSED(type);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TMultiExprType& type) {
- for (const auto& i : type.GetItems()) {
- i->Accept(*this);
- }
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TTupleExprType& type) {
- for (const auto& i : type.GetItems()) {
- i->Accept(*this);
- }
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TStructExprType& type) {
- for (const auto& i : type.GetItems()) {
- i->Accept(*this);
- }
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TItemExprType& type) {
- type.GetItemType()->Accept(*this);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TListExprType& type) {
- type.GetItemType()->Accept(*this);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TStreamExprType& type) {
- type.GetItemType()->Accept(*this);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TFlowExprType& type) {
- type.GetItemType()->Accept(*this);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TDataExprType& type) {
- Y_UNUSED(type);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TPgExprType& type) {
- Y_UNUSED(type);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TWorldExprType& type) {
- Y_UNUSED(type);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TOptionalExprType& type) {
- type.GetItemType()->Accept(*this);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TCallableExprType& type) {
- type.GetReturnType()->Accept(*this);
- for (const auto& arg : type.GetArguments()) {
- arg.Type->Accept(*this);
- }
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TResourceExprType& type) {
- Y_UNUSED(type);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TTypeExprType& type) {
- type.GetType()->Accept(*this);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TDictExprType& type) {
- type.GetKeyType()->Accept(*this);
- type.GetPayloadType()->Accept(*this);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TVoidExprType& type) {
- Y_UNUSED(type);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TNullExprType& type) {
- Y_UNUSED(type);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TGenericExprType& type) {
- Y_UNUSED(type);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TTaggedExprType& type) {
- type.GetBaseType()->Accept(*this);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TErrorExprType& type) {
- Y_UNUSED(type);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TVariantExprType& type) {
- type.GetUnderlyingType()->Accept(*this);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TEmptyListExprType& type) {
- Y_UNUSED(type);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TEmptyDictExprType& type) {
- Y_UNUSED(type);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TBlockExprType& type) {
- type.GetItemType()->Accept(*this);
- }
- void TDefaultTypeAnnotationVisitor::Visit(const TScalarExprType& type) {
- type.GetItemType()->Accept(*this);
- }
- TErrorTypeVisitor::TErrorTypeVisitor(TExprContext& ctx)
- : Ctx_(ctx)
- {}
- void TErrorTypeVisitor::Visit(const TErrorExprType& type) {
- HasErrors_ = true;
- Ctx_.IssueManager.RaiseIssue(type.GetError());
- }
- bool TErrorTypeVisitor::HasErrors() const {
- return HasErrors_;
- }
- } // namespace NYql
- template<>
- void Out<NYql::TExprNode::EType>(class IOutputStream &o, NYql::TExprNode::EType x) {
- #define YQL_EXPR_NODE_TYPE_MAP_TO_STRING_IMPL(name, ...) \
- case NYql::TExprNode::name: \
- o << #name; \
- return;
- switch (x) {
- YQL_EXPR_NODE_TYPE_MAP(YQL_EXPR_NODE_TYPE_MAP_TO_STRING_IMPL)
- default:
- o << static_cast<int>(x);
- return;
- }
- }
- template<>
- void Out<NYql::TExprNode::EState>(class IOutputStream &o, NYql::TExprNode::EState x) {
- #define YQL_EXPR_NODE_STATE_MAP_TO_STRING_IMPL(name, ...) \
- case NYql::TExprNode::EState::name: \
- o << #name; \
- return;
- switch (x) {
- YQL_EXPR_NODE_STATE_MAP(YQL_EXPR_NODE_STATE_MAP_TO_STRING_IMPL)
- default:
- o << static_cast<int>(x);
- return;
- }
- }
|