12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917 |
- #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;
- }
- } // 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;
- }
- }
|