mkql_node.cpp 79 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538
  1. #include "mkql_node.h"
  2. #include "mkql_node_builder.h"
  3. #include "mkql_node_cast.h"
  4. #include "mkql_node_visitor.h"
  5. #include "mkql_node_printer.h"
  6. #include "mkql_runtime_version.h"
  7. #include <yql/essentials/parser/pg_catalog/catalog.h>
  8. #include <util/stream/str.h>
  9. #include <util/string/join.h>
  10. namespace NKikimr {
  11. namespace NMiniKQL {
  12. #define MKQL_SWITCH_ENUM_TYPE_TO_STR(name, val) \
  13. case val: return TStringBuf(#name);
  14. using namespace NDetail;
  15. TTypeEnvironment::TTypeEnvironment(TScopedAlloc& alloc)
  16. : Alloc(alloc)
  17. , Arena(&Alloc.Ref())
  18. , EmptyStruct(nullptr)
  19. , EmptyTuple(nullptr)
  20. {
  21. }
  22. TTypeEnvironment::~TTypeEnvironment() {
  23. }
  24. void TTypeEnvironment::ClearCookies() const {
  25. if (TypeOfType) {
  26. TypeOfType->SetCookie(0);
  27. }
  28. if (TypeOfVoid) {
  29. TypeOfVoid->SetCookie(0);
  30. }
  31. if (Void) {
  32. Void->SetCookie(0);
  33. }
  34. if (TypeOfNull) {
  35. TypeOfNull->SetCookie(0);
  36. }
  37. if (Null) {
  38. Null->SetCookie(0);
  39. }
  40. if (TypeOfEmptyList) {
  41. TypeOfEmptyList->SetCookie(0);
  42. }
  43. if (EmptyList) {
  44. EmptyList->SetCookie(0);
  45. }
  46. if (TypeOfEmptyDict) {
  47. TypeOfEmptyDict->SetCookie(0);
  48. }
  49. if (EmptyDict) {
  50. EmptyDict->SetCookie(0);
  51. }
  52. if (EmptyStruct) {
  53. EmptyStruct->SetCookie(0);
  54. }
  55. if (ListOfVoid) {
  56. ListOfVoid->SetCookie(0);
  57. }
  58. if (AnyType) {
  59. AnyType->SetCookie(0);
  60. }
  61. if (EmptyTuple) {
  62. EmptyTuple->SetCookie(0);
  63. }
  64. }
  65. TTypeType* TTypeEnvironment::GetTypeOfTypeLazy() const {
  66. if (!TypeOfType) {
  67. TypeOfType = TTypeType::Create(*this);
  68. TypeOfType->Type = TypeOfType;
  69. }
  70. return TypeOfType;
  71. }
  72. TVoidType* TTypeEnvironment::GetTypeOfVoidLazy() const {
  73. if (!TypeOfVoid) {
  74. TypeOfVoid = TVoidType::Create(GetTypeOfTypeLazy(), *this);
  75. }
  76. return TypeOfVoid;
  77. }
  78. TVoid* TTypeEnvironment::GetVoidLazy() const {
  79. if (!Void) {
  80. Void = TVoid::Create(*this);
  81. }
  82. return Void;
  83. }
  84. TNullType* TTypeEnvironment::GetTypeOfNullLazy() const {
  85. if (!TypeOfNull) {
  86. TypeOfNull = TNullType::Create(GetTypeOfTypeLazy(), *this);
  87. }
  88. return TypeOfNull;
  89. }
  90. TNull* TTypeEnvironment::GetNullLazy() const {
  91. if (!Null) {
  92. Null = TNull::Create(*this);
  93. }
  94. return Null;
  95. }
  96. TEmptyListType* TTypeEnvironment::GetTypeOfEmptyListLazy() const {
  97. if (!TypeOfEmptyList) {
  98. TypeOfEmptyList = TEmptyListType::Create(GetTypeOfTypeLazy(), *this);
  99. }
  100. return TypeOfEmptyList;
  101. }
  102. TEmptyList* TTypeEnvironment::GetEmptyListLazy() const {
  103. if (!EmptyList) {
  104. EmptyList = TEmptyList::Create(*this);
  105. }
  106. return EmptyList;
  107. }
  108. TEmptyDictType* TTypeEnvironment::GetTypeOfEmptyDictLazy() const {
  109. if (!TypeOfEmptyDict) {
  110. TypeOfEmptyDict = TEmptyDictType::Create(GetTypeOfTypeLazy(), *this);
  111. }
  112. return TypeOfEmptyDict;
  113. }
  114. TEmptyDict* TTypeEnvironment::GetEmptyDictLazy() const {
  115. if (!EmptyDict) {
  116. EmptyDict = TEmptyDict::Create(*this);
  117. }
  118. return EmptyDict;
  119. }
  120. TStructLiteral* TTypeEnvironment::GetEmptyStructLazy() const {
  121. if (!EmptyStruct) {
  122. EmptyStruct = TStructLiteral::Create(
  123. 0,
  124. nullptr,
  125. TStructType::Create(0, nullptr, *this), *this, false);
  126. }
  127. return EmptyStruct;
  128. }
  129. TListLiteral* TTypeEnvironment::GetListOfVoidLazy() const {
  130. if (!ListOfVoid) {
  131. ListOfVoid = TListLiteral::Create(nullptr, 0, TListType::Create(GetVoidLazy()->GetGenericType(), *this), *this);
  132. }
  133. return ListOfVoid;
  134. }
  135. TAnyType* TTypeEnvironment::GetAnyTypeLazy() const {
  136. if (!AnyType) {
  137. AnyType = TAnyType::Create(GetTypeOfTypeLazy(), *this);
  138. }
  139. return AnyType;
  140. }
  141. TTupleLiteral* TTypeEnvironment::GetEmptyTupleLazy() const {
  142. if (!EmptyTuple) {
  143. EmptyTuple = TTupleLiteral::Create(0, nullptr, TTupleType::Create(0, nullptr, *this), *this, false);
  144. }
  145. return EmptyTuple;
  146. }
  147. TDataType* TTypeEnvironment::GetUi32Lazy() const {
  148. if (!Ui32) {
  149. Ui32 = TDataType::Create(NUdf::TDataType<ui32>::Id, *this);
  150. }
  151. return Ui32;
  152. }
  153. TDataType* TTypeEnvironment::GetUi64Lazy() const {
  154. if (!Ui64) {
  155. Ui64 = TDataType::Create(NUdf::TDataType<ui64>::Id, *this);
  156. }
  157. return Ui64;
  158. }
  159. std::vector<TNode*>& TTypeEnvironment::GetNodeStack() const {
  160. return Stack;
  161. }
  162. TInternName TTypeEnvironment::InternName(const TStringBuf& name) const {
  163. if (NamesPool.empty()) {
  164. NamesPool.reserve(64);
  165. }
  166. auto it = NamesPool.find(name);
  167. if (it != NamesPool.end()) {
  168. return TInternName(*it);
  169. }
  170. // Copy to arena and null-terminate
  171. char* data = (char*)AllocateBuffer(name.size()+1);
  172. memcpy(data, name.data(), name.size());
  173. data[name.size()] = 0;
  174. return TInternName(*NamesPool.insert(TStringBuf(data, name.size())).first);
  175. }
  176. #define LITERALS_LIST(xx) \
  177. xx(Void, TVoid) \
  178. xx(Null, TNull) \
  179. xx(EmptyList, TEmptyList) \
  180. xx(EmptyDict, TEmptyDict) \
  181. xx(Data, TDataLiteral) \
  182. xx(Struct, TStructLiteral) \
  183. xx(List, TListLiteral) \
  184. xx(Optional, TOptionalLiteral) \
  185. xx(Dict, TDictLiteral) \
  186. xx(Callable, TCallable) \
  187. xx(Any, TAny) \
  188. xx(Tuple, TTupleLiteral) \
  189. xx(Variant, TVariantLiteral)
  190. void TNode::Accept(INodeVisitor& visitor) {
  191. const auto kind = Type->GetKind();
  192. switch (kind) {
  193. case TType::EKind::Type:
  194. return static_cast<TType&>(*this).Accept(visitor);
  195. #define APPLY(kind, type) \
  196. case TType::EKind::kind: \
  197. return visitor.Visit(static_cast<type&>(*this));
  198. LITERALS_LIST(APPLY)
  199. #undef APPLY
  200. default:
  201. Y_ABORT();
  202. }
  203. }
  204. bool TNode::Equals(const TNode& nodeToCompare) const {
  205. if (this == &nodeToCompare)
  206. return true;
  207. if (!Type->IsSameType(*nodeToCompare.Type))
  208. return false;
  209. const auto kind = Type->GetKind();
  210. switch (kind) {
  211. case TType::EKind::Type:
  212. return static_cast<const TType&>(*this).IsSameType(static_cast<const TType&>(nodeToCompare));
  213. #define APPLY(kind, type) \
  214. case TType::EKind::kind: \
  215. return static_cast<const type&>(*this).Equals(static_cast<const type&>(nodeToCompare));
  216. LITERALS_LIST(APPLY)
  217. #undef APPLY
  218. default:
  219. Y_ABORT();
  220. }
  221. }
  222. void TNode::UpdateLinks(const THashMap<TNode*, TNode*>& links) {
  223. const auto kind = Type->GetKind();
  224. switch (kind) {
  225. case TType::EKind::Type:
  226. return static_cast<TType&>(*this).UpdateLinks(links);
  227. #define APPLY(kind, type) \
  228. case TType::EKind::kind: \
  229. return static_cast<type&>(*this).DoUpdateLinks(links);
  230. LITERALS_LIST(APPLY)
  231. #undef APPLY
  232. default:
  233. Y_ABORT();
  234. }
  235. }
  236. TNode* TNode::CloneOnCallableWrite(const TTypeEnvironment& env) const {
  237. const auto kind = Type->GetKind();
  238. switch (kind) {
  239. case TType::EKind::Type:
  240. return static_cast<const TType&>(*this).CloneOnCallableWrite(env);
  241. #define APPLY(kind, type) \
  242. case TType::EKind::kind: \
  243. return static_cast<const type&>(*this).DoCloneOnCallableWrite(env);
  244. LITERALS_LIST(APPLY)
  245. #undef APPLY
  246. default:
  247. Y_ABORT();
  248. }
  249. }
  250. void TNode::Freeze(const TTypeEnvironment& env) {
  251. const auto kind = Type->GetKind();
  252. switch (kind) {
  253. case TType::EKind::Type:
  254. return static_cast<TType&>(*this).Freeze(env);
  255. #define APPLY(kind, type) \
  256. case TType::EKind::kind: \
  257. return static_cast<type&>(*this).DoFreeze(env);
  258. LITERALS_LIST(APPLY)
  259. #undef APPLY
  260. default:
  261. Y_ABORT();
  262. }
  263. }
  264. bool TNode::IsMergeable() const {
  265. if (!Type->IsCallable()) {
  266. return true;
  267. }
  268. return !static_cast<const TCallable*>(this)->GetType()->IsMergeDisabled();
  269. }
  270. TStringBuf TType::KindAsStr(EKind kind) {
  271. switch (static_cast<int>(kind)) {
  272. MKQL_TYPE_KINDS(MKQL_SWITCH_ENUM_TYPE_TO_STR)
  273. }
  274. return TStringBuf("unknown");
  275. }
  276. TStringBuf TType::GetKindAsStr() const {
  277. return KindAsStr(Kind);
  278. }
  279. #define TYPES_LIST(xx) \
  280. xx(Type, TTypeType) \
  281. xx(Void, TVoidType) \
  282. xx(Data, TDataType) \
  283. xx(Struct, TStructType) \
  284. xx(List, TListType) \
  285. xx(Stream, TStreamType) \
  286. xx(Optional, TOptionalType) \
  287. xx(Dict, TDictType) \
  288. xx(Callable, TCallableType) \
  289. xx(Any, TAnyType) \
  290. xx(Tuple, TTupleType) \
  291. xx(Resource, TResourceType) \
  292. xx(Variant, TVariantType) \
  293. xx(Flow, TFlowType) \
  294. xx(Null, TNullType) \
  295. xx(EmptyList, TEmptyListType) \
  296. xx(EmptyDict, TEmptyDictType) \
  297. xx(Tagged, TTaggedType) \
  298. xx(Block, TBlockType) \
  299. xx(Pg, TPgType) \
  300. xx(Multi, TMultiType) \
  301. void TType::Accept(INodeVisitor& visitor) {
  302. switch (Kind) {
  303. #define APPLY(kind, type) \
  304. case EKind::kind: \
  305. return visitor.Visit(static_cast<type&>(*this));
  306. TYPES_LIST(APPLY)
  307. #undef APPLY
  308. default:
  309. Y_ABORT();
  310. }
  311. }
  312. void TType::UpdateLinks(const THashMap<TNode*, TNode*>& links) {
  313. switch (Kind) {
  314. #define APPLY(kind, type) \
  315. case EKind::kind: \
  316. return static_cast<type&>(*this).DoUpdateLinks(links);
  317. TYPES_LIST(APPLY)
  318. #undef APPLY
  319. default:
  320. Y_ABORT();
  321. }
  322. }
  323. TNode* TType::CloneOnCallableWrite(const TTypeEnvironment& env) const {
  324. switch (Kind) {
  325. #define APPLY(kind, type) \
  326. case EKind::kind: \
  327. return static_cast<const type&>(*this).DoCloneOnCallableWrite(env);
  328. TYPES_LIST(APPLY)
  329. #undef APPLY
  330. default:
  331. Y_ABORT();
  332. }
  333. }
  334. void TType::Freeze(const TTypeEnvironment& env) {
  335. switch (Kind) {
  336. #define APPLY(kind, type) \
  337. case EKind::kind: \
  338. return static_cast<type&>(*this).DoFreeze(env);
  339. TYPES_LIST(APPLY)
  340. #undef APPLY
  341. default:
  342. Y_ABORT();
  343. }
  344. }
  345. bool TTypeBase::IsSameType(const TTypeBase& typeToCompare) const {
  346. if (Kind != typeToCompare.Kind) {
  347. return false;
  348. }
  349. switch (Kind) {
  350. #define APPLY(kind, type) \
  351. case EKind::kind: \
  352. return static_cast<const type&>(*this).IsSameType(static_cast<const type&>(typeToCompare));
  353. TYPES_LIST(APPLY)
  354. #undef APPLY
  355. default:
  356. Y_ABORT();
  357. }
  358. }
  359. size_t TTypeBase::CalcHash() const {
  360. switch (Kind) {
  361. #define APPLY(kind, type) \
  362. case EKind::kind: \
  363. /* combine hashes to aviod collision, for example, between Kind and SchemeType */ \
  364. return CombineHashes(IntHash((size_t)Kind), static_cast<const type&>(*this).CalcHash());
  365. TYPES_LIST(APPLY)
  366. #undef APPLY
  367. default:
  368. Y_ABORT();
  369. }
  370. }
  371. bool TType::IsConvertableTo(const TType& typeToCompare, bool ignoreTagged) const {
  372. const TType* self = this;
  373. const TType* other = &typeToCompare;
  374. if (ignoreTagged) {
  375. while (self->Kind == EKind::Tagged) {
  376. self = static_cast<const TTaggedType*>(self)->GetBaseType();
  377. }
  378. while (other->Kind == EKind::Tagged) {
  379. other = static_cast<const TTaggedType*>(other)->GetBaseType();
  380. }
  381. }
  382. if (self->Kind != other->Kind) {
  383. return false;
  384. }
  385. switch (self->Kind) {
  386. #define APPLY(kind, type) \
  387. case EKind::kind: \
  388. return static_cast<const type&>(*self).IsConvertableTo(static_cast<const type&>(*other), ignoreTagged);
  389. TYPES_LIST(APPLY)
  390. #undef APPLY
  391. default:
  392. Y_ABORT();
  393. }
  394. }
  395. TTypeType* TTypeType::Create(const TTypeEnvironment& env) {
  396. return ::new(env.Allocate<TTypeType>()) TTypeType();
  397. }
  398. bool TTypeType::IsSameType(const TTypeType& typeToCompare) const {
  399. Y_UNUSED(typeToCompare);
  400. return true;
  401. }
  402. size_t TTypeType::CalcHash() const {
  403. return 0;
  404. }
  405. bool TTypeType::IsConvertableTo(const TTypeType& typeToCompare, bool ignoreTagged) const {
  406. Y_UNUSED(ignoreTagged);
  407. return IsSameType(typeToCompare);
  408. }
  409. void TTypeType::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  410. Y_UNUSED(links);
  411. }
  412. TNode* TTypeType::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  413. Y_UNUSED(env);
  414. return const_cast<TTypeType*>(this);
  415. }
  416. void TTypeType::DoFreeze(const TTypeEnvironment& env) {
  417. Y_UNUSED(env);
  418. }
  419. TDataType::TDataType(NUdf::TDataTypeId schemeType, const TTypeEnvironment& env)
  420. : TType(EKind::Data, env.GetTypeOfTypeLazy(), true)
  421. , SchemeType(schemeType)
  422. , DataSlot(NUdf::FindDataSlot(schemeType))
  423. {
  424. }
  425. TDataType* TDataType::Create(NUdf::TDataTypeId schemeType, const TTypeEnvironment& env) {
  426. MKQL_ENSURE(schemeType, "Null type isn't allowed.");
  427. MKQL_ENSURE(schemeType != NUdf::TDataType<NUdf::TDecimal>::Id, "Can't' create Decimal.");
  428. MKQL_ENSURE(schemeType != 0, "0 type");
  429. return ::new(env.Allocate<TDataType>()) TDataType(schemeType, env);
  430. }
  431. bool TDataType::IsSameType(const TDataType& typeToCompare) const {
  432. if (SchemeType != typeToCompare.SchemeType)
  433. return false;
  434. if (SchemeType != NUdf::TDataType<NUdf::TDecimal>::Id)
  435. return true;
  436. return static_cast<const TDataDecimalType&>(*this).IsSameType(static_cast<const TDataDecimalType&>(typeToCompare));
  437. }
  438. size_t TDataType::CalcHash() const {
  439. size_t hash = IntHash((size_t)GetSchemeType());
  440. if (SchemeType == NUdf::TDataType<NUdf::TDecimal>::Id) {
  441. hash = CombineHashes(hash, static_cast<const TDataDecimalType&>(*this).CalcHash());
  442. }
  443. return hash;
  444. }
  445. bool TDataType::IsConvertableTo(const TDataType& typeToCompare, bool ignoreTagged) const {
  446. Y_UNUSED(ignoreTagged);
  447. return IsSameType(typeToCompare);
  448. }
  449. void TDataType::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  450. Y_UNUSED(links);
  451. }
  452. TNode* TDataType::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  453. Y_UNUSED(env);
  454. return const_cast<TDataType*>(this);
  455. }
  456. void TDataType::DoFreeze(const TTypeEnvironment& env) {
  457. Y_UNUSED(env);
  458. }
  459. TDataDecimalType::TDataDecimalType(ui8 precision, ui8 scale, const TTypeEnvironment& env)
  460. : TDataType(NUdf::TDataType<NUdf::TDecimal>::Id, env), Precision(precision), Scale(scale)
  461. {
  462. MKQL_ENSURE(Precision > 0, "Precision must be positive.");
  463. MKQL_ENSURE(Scale <= Precision, "Scale too large.");
  464. }
  465. TDataDecimalType* TDataDecimalType::Create(ui8 precision, ui8 scale, const TTypeEnvironment& env) {
  466. return ::new(env.Allocate<TDataDecimalType>()) TDataDecimalType(precision, scale, env);
  467. }
  468. bool TDataDecimalType::IsSameType(const TDataDecimalType& typeToCompare) const {
  469. return Precision == typeToCompare.Precision && Scale == typeToCompare.Scale;
  470. }
  471. size_t TDataDecimalType::CalcHash() const {
  472. return CombineHashes(IntHash((size_t)Precision), IntHash((size_t)Scale));
  473. }
  474. bool TDataDecimalType::IsConvertableTo(const TDataDecimalType& typeToCompare, bool ignoreTagged) const {
  475. Y_UNUSED(ignoreTagged);
  476. return Precision == typeToCompare.Precision && Scale == typeToCompare.Scale;
  477. }
  478. std::pair<ui8, ui8> TDataDecimalType::GetParams() const {
  479. return std::make_pair(Precision, Scale);
  480. }
  481. TDataLiteral::TDataLiteral(const TUnboxedValuePod& value, TDataType* type)
  482. : TNode(type), TUnboxedValuePod(value)
  483. {}
  484. TDataLiteral* TDataLiteral::Create(const NUdf::TUnboxedValuePod& value, TDataType* type, const TTypeEnvironment& env) {
  485. return ::new(env.Allocate<TDataLiteral>()) TDataLiteral(value, type);
  486. }
  487. void TDataLiteral::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  488. auto typeIt = links.find(Type);
  489. if (typeIt != links.end()) {
  490. TNode* newNode = typeIt->second;
  491. Y_DEBUG_ABORT_UNLESS(Type->Equals(*newNode));
  492. Type = static_cast<TType*>(newNode);
  493. }
  494. }
  495. TNode* TDataLiteral::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  496. Y_UNUSED(env);
  497. return const_cast<TDataLiteral*>(this);
  498. }
  499. void TDataLiteral::DoFreeze(const TTypeEnvironment& env) {
  500. Y_UNUSED(env);
  501. }
  502. bool TDataLiteral::Equals(const TDataLiteral& nodeToCompare) const {
  503. const auto& self = AsValue();
  504. const auto& that = nodeToCompare.AsValue();
  505. switch (GetType()->GetSchemeType()) {
  506. case NUdf::TDataType<bool>::Id: return self.Get<bool>() == that.Get<bool>();
  507. case NUdf::TDataType<ui8>::Id: return self.Get<ui8>() == that.Get<ui8>();
  508. case NUdf::TDataType<i8>::Id: return self.Get<i8>() == that.Get<i8>();
  509. case NUdf::TDataType<NUdf::TDate>::Id:
  510. case NUdf::TDataType<ui16>::Id: return self.Get<ui16>() == that.Get<ui16>();
  511. case NUdf::TDataType<i16>::Id: return self.Get<i16>() == that.Get<i16>();
  512. case NUdf::TDataType<NUdf::TDate32>::Id:
  513. case NUdf::TDataType<i32>::Id: return self.Get<i32>() == that.Get<i32>();
  514. case NUdf::TDataType<NUdf::TDatetime>::Id:
  515. case NUdf::TDataType<ui32>::Id: return self.Get<ui32>() == that.Get<ui32>();
  516. case NUdf::TDataType<NUdf::TInterval>::Id:
  517. case NUdf::TDataType<NUdf::TInterval64>::Id:
  518. case NUdf::TDataType<NUdf::TDatetime64>::Id:
  519. case NUdf::TDataType<NUdf::TTimestamp64>::Id:
  520. case NUdf::TDataType<i64>::Id: return self.Get<i64>() == that.Get<i64>();
  521. case NUdf::TDataType<NUdf::TTimestamp>::Id:
  522. case NUdf::TDataType<ui64>::Id: return self.Get<ui64>() == that.Get<ui64>();
  523. case NUdf::TDataType<float>::Id: return self.Get<float>() == that.Get<float>();
  524. case NUdf::TDataType<double>::Id: return self.Get<double>() == that.Get<double>();
  525. case NUdf::TDataType<NUdf::TTzDate>::Id: return self.Get<ui16>() == that.Get<ui16>() && self.GetTimezoneId() == that.GetTimezoneId();
  526. case NUdf::TDataType<NUdf::TTzDatetime>::Id: return self.Get<ui32>() == that.Get<ui32>() && self.GetTimezoneId() == that.GetTimezoneId();
  527. case NUdf::TDataType<NUdf::TTzTimestamp>::Id: return self.Get<ui64>() == that.Get<ui64>() && self.GetTimezoneId() == that.GetTimezoneId();
  528. case NUdf::TDataType<NUdf::TDecimal>::Id: return self.GetInt128() == that.GetInt128();
  529. default: return self.AsStringRef() == that.AsStringRef();
  530. }
  531. }
  532. static const THashSet<TStringBuf> PG_SUPPORTED_PRESORT = {
  533. "bool",
  534. "int2",
  535. "int4",
  536. "int8",
  537. "float4",
  538. "float8",
  539. "bytea",
  540. "varchar",
  541. "text",
  542. "cstring"
  543. };
  544. TPgType::TPgType(ui32 typeId, const TTypeEnvironment& env)
  545. : TType(EKind::Pg, env.GetTypeOfTypeLazy(),
  546. NYql::NPg::HasType(typeId) && PG_SUPPORTED_PRESORT.contains(NYql::NPg::LookupType(typeId).Name))
  547. , TypeId(typeId)
  548. {
  549. }
  550. TPgType* TPgType::Create(ui32 typeId, const TTypeEnvironment& env) {
  551. MKQL_ENSURE(typeId != 0, "0 type");
  552. return ::new(env.Allocate<TPgType>()) TPgType(typeId, env);
  553. }
  554. bool TPgType::IsSameType(const TPgType& typeToCompare) const {
  555. return TypeId == typeToCompare.TypeId;
  556. }
  557. size_t TPgType::CalcHash() const {
  558. return IntHash((size_t)TypeId);
  559. }
  560. bool TPgType::IsConvertableTo(const TPgType& typeToCompare, bool ignoreTagged) const {
  561. Y_UNUSED(ignoreTagged);
  562. return IsSameType(typeToCompare);
  563. }
  564. void TPgType::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  565. Y_UNUSED(links);
  566. }
  567. TNode* TPgType::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  568. Y_UNUSED(env);
  569. return const_cast<TPgType*>(this);
  570. }
  571. void TPgType::DoFreeze(const TTypeEnvironment& env) {
  572. Y_UNUSED(env);
  573. }
  574. const TString& TPgType::GetName() const {
  575. return NYql::NPg::LookupType(TypeId).Name;
  576. }
  577. TStructType::TStructType(ui32 membersCount, std::pair<TInternName, TType*>* members, const TTypeEnvironment& env,
  578. bool validate)
  579. : TType(EKind::Struct, env.GetTypeOfTypeLazy(), CalculatePresortSupport(membersCount, members))
  580. , MembersCount(membersCount)
  581. , Members(members)
  582. {
  583. if (!validate)
  584. return;
  585. TInternName lastMemberName;
  586. for (size_t index = 0; index < membersCount; ++index) {
  587. const auto& name = Members[index].first;
  588. MKQL_ENSURE(!name.Str().empty(), "Empty member name is not allowed");
  589. MKQL_ENSURE(name.Str() > lastMemberName.Str(), "Member names are not sorted: "
  590. << name.Str() << " <= " << lastMemberName.Str());
  591. lastMemberName = name;
  592. }
  593. }
  594. TStructType* TStructType::Create(const std::pair<TString, TType*>* members, ui32 membersCount, const TTypeEnvironment& env) {
  595. std::pair<TInternName, TType*>* allocatedMembers = nullptr;
  596. if (membersCount) {
  597. allocatedMembers = static_cast<std::pair<TInternName, TType*>*>(env.AllocateBuffer(membersCount * sizeof(*allocatedMembers)));
  598. for (ui32 i = 0; i < membersCount; ++i) {
  599. allocatedMembers[i] = std::make_pair(env.InternName(members[i].first), members[i].second);
  600. }
  601. }
  602. return ::new(env.Allocate<TStructType>()) TStructType(membersCount, allocatedMembers, env);
  603. }
  604. TStructType* TStructType::Create(ui32 membersCount, const TStructMember* members, const TTypeEnvironment& env) {
  605. std::pair<TInternName, TType*>* allocatedMembers = nullptr;
  606. if (membersCount) {
  607. allocatedMembers = static_cast<std::pair<TInternName, TType*>*>(env.AllocateBuffer(membersCount * sizeof(*allocatedMembers)));
  608. for (ui32 i = 0; i < membersCount; ++i) {
  609. allocatedMembers[i] = std::make_pair(env.InternName(members[i].Name), members[i].Type);
  610. }
  611. }
  612. return ::new(env.Allocate<TStructType>()) TStructType(membersCount, allocatedMembers, env);
  613. }
  614. bool TStructType::IsSameType(const TStructType& typeToCompare) const {
  615. if (this == &typeToCompare)
  616. return true;
  617. if (MembersCount != typeToCompare.MembersCount)
  618. return false;
  619. for (size_t index = 0; index < MembersCount; ++index) {
  620. if (Members[index].first != typeToCompare.Members[index].first)
  621. return false;
  622. if (!Members[index].second->IsSameType(*typeToCompare.Members[index].second))
  623. return false;
  624. }
  625. return true;
  626. }
  627. size_t TStructType::CalcHash() const {
  628. size_t hash = 0;
  629. for (size_t i = 0; i < MembersCount; ++i) {
  630. hash = CombineHashes(hash, Members[i].first.Hash());
  631. hash = CombineHashes(hash, Members[i].second->CalcHash());
  632. }
  633. return hash;
  634. }
  635. bool TStructType::IsConvertableTo(const TStructType& typeToCompare, bool ignoreTagged) const {
  636. if (this == &typeToCompare)
  637. return true;
  638. if (MembersCount != typeToCompare.MembersCount)
  639. return false;
  640. for (size_t index = 0; index < MembersCount; ++index) {
  641. if (Members[index].first != typeToCompare.Members[index].first)
  642. return false;
  643. if (!Members[index].second->IsConvertableTo(*typeToCompare.Members[index].second, ignoreTagged))
  644. return false;
  645. }
  646. return true;
  647. }
  648. void TStructType::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  649. for (ui32 i = 0; i < MembersCount; ++i) {
  650. auto& member = Members[i];
  651. auto memberIt = links.find(member.second);
  652. if (memberIt != links.end()) {
  653. TNode* newNode = memberIt->second;
  654. Y_DEBUG_ABORT_UNLESS(member.second->Equals(*newNode));
  655. member.second = static_cast<TType*>(newNode);
  656. }
  657. }
  658. }
  659. TNode* TStructType::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  660. bool needClone = false;
  661. for (ui32 i = 0; i < MembersCount; ++i) {
  662. if (Members[i].second->GetCookie()) {
  663. needClone = true;
  664. break;
  665. }
  666. }
  667. if (!needClone)
  668. return const_cast<TStructType*>(this);
  669. std::pair<TInternName, TType*>* allocatedMembers = nullptr;
  670. if (MembersCount) {
  671. allocatedMembers = static_cast<std::pair<TInternName, TType*>*>(env.AllocateBuffer(MembersCount * sizeof(*allocatedMembers)));
  672. for (ui32 i = 0; i < MembersCount; ++i) {
  673. allocatedMembers[i].first = Members[i].first;
  674. auto newNode = (TNode*)Members[i].second->GetCookie();
  675. if (newNode) {
  676. allocatedMembers[i].second = static_cast<TType*>(newNode);
  677. } else {
  678. allocatedMembers[i].second = Members[i].second;
  679. }
  680. }
  681. }
  682. return ::new(env.Allocate<TStructType>()) TStructType(MembersCount, allocatedMembers, env, false);
  683. }
  684. void TStructType::DoFreeze(const TTypeEnvironment& env) {
  685. Y_UNUSED(env);
  686. }
  687. bool TStructType::CalculatePresortSupport(ui32 membersCount, std::pair<TInternName, TType*>* members) {
  688. for (ui32 i = 0; i < membersCount; ++i) {
  689. if (!members[i].second->IsPresortSupported()) {
  690. return false;
  691. }
  692. }
  693. return true;
  694. }
  695. ui32 TStructType::GetMemberIndex(const TStringBuf& name) const {
  696. auto index = FindMemberIndex(name);
  697. if (index) {
  698. return *index;
  699. }
  700. TStringStream ss;
  701. for (ui32 i = 0; i < MembersCount; ++i) {
  702. ss << " " << Members[i].first.Str();
  703. }
  704. THROW yexception() << "Member with name '" << name << "' not found; "
  705. << " known members: " << ss.Str() << ".";
  706. }
  707. TMaybe<ui32> TStructType::FindMemberIndex(const TStringBuf& name) const {
  708. for (ui32 i = 0; i < MembersCount; ++i) {
  709. if (Members[i].first == name)
  710. return i;
  711. }
  712. return {};
  713. }
  714. TStructLiteral::TStructLiteral(TRuntimeNode* values, TStructType* type, bool validate)
  715. : TNode(type)
  716. , Values(values)
  717. {
  718. if (!validate) {
  719. for (size_t index = 0; index < GetValuesCount(); ++index) {
  720. auto& value = Values[index];
  721. value.Freeze();
  722. }
  723. return;
  724. }
  725. for (size_t index = 0; index < GetValuesCount(); ++index) {
  726. MKQL_ENSURE(!type->GetMemberName(index).empty(), "Empty struct member name is not allowed");
  727. auto& value = Values[index];
  728. MKQL_ENSURE(value.GetStaticType()->IsSameType(*type->GetMemberType(index)), "Wrong type of member");
  729. value.Freeze();
  730. }
  731. }
  732. TStructLiteral* TStructLiteral::Create(ui32 valuesCount, const TRuntimeNode* values, TStructType* type, const TTypeEnvironment& env, bool useCachedEmptyStruct) {
  733. MKQL_ENSURE(valuesCount == type->GetMembersCount(), "Wrong count of members");
  734. TRuntimeNode* allocatedValues = nullptr;
  735. if (valuesCount) {
  736. allocatedValues = static_cast<TRuntimeNode*>(env.AllocateBuffer(valuesCount * sizeof(*allocatedValues)));
  737. for (ui32 i = 0; i < valuesCount; ++i) {
  738. allocatedValues[i] = values[i];
  739. }
  740. } else if (useCachedEmptyStruct) {
  741. return env.GetEmptyStructLazy();
  742. }
  743. return ::new(env.Allocate<TStructLiteral>()) TStructLiteral(allocatedValues, type);
  744. }
  745. void TStructLiteral::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  746. auto typeIt = links.find(Type);
  747. if (typeIt != links.end()) {
  748. TNode* newNode = typeIt->second;
  749. Y_DEBUG_ABORT_UNLESS(Type->Equals(*newNode));
  750. Type = static_cast<TType*>(newNode);
  751. }
  752. for (ui32 i = 0; i < GetValuesCount(); ++i) {
  753. auto& value = Values[i];
  754. auto valueIt = links.find(value.GetNode());
  755. if (valueIt != links.end()) {
  756. TNode* newNode = valueIt->second;
  757. Y_DEBUG_ABORT_UNLESS(value.GetNode()->Equals(*newNode));
  758. value = TRuntimeNode(newNode, value.IsImmediate());
  759. }
  760. }
  761. }
  762. TNode* TStructLiteral::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  763. auto typeNewNode = (TNode*)Type->GetCookie();
  764. bool needClone = false;
  765. if (typeNewNode) {
  766. needClone = true;
  767. } else {
  768. for (ui32 i = 0; i < GetValuesCount(); ++i) {
  769. if (Values[i].GetNode()->GetCookie()) {
  770. needClone = true;
  771. break;
  772. }
  773. }
  774. }
  775. if (!needClone)
  776. return const_cast<TStructLiteral*>(this);
  777. TRuntimeNode* allocatedValues = nullptr;
  778. if (GetValuesCount()) {
  779. allocatedValues = static_cast<TRuntimeNode*>(env.AllocateBuffer(GetValuesCount() * sizeof(*allocatedValues)));
  780. for (ui32 i = 0; i < GetValuesCount(); ++i) {
  781. allocatedValues[i] = Values[i];
  782. auto newNode = (TNode*)Values[i].GetNode()->GetCookie();
  783. if (newNode) {
  784. allocatedValues[i] = TRuntimeNode(newNode, Values[i].IsImmediate());
  785. }
  786. }
  787. }
  788. return ::new(env.Allocate<TStructLiteral>()) TStructLiteral(allocatedValues,
  789. typeNewNode ? static_cast<TStructType*>(typeNewNode) : GetType(), false);
  790. }
  791. void TStructLiteral::DoFreeze(const TTypeEnvironment& env) {
  792. Y_UNUSED(env);
  793. for (ui32 i = 0; i < GetValuesCount(); ++i) {
  794. Values[i].Freeze();
  795. }
  796. }
  797. bool TStructLiteral::Equals(const TStructLiteral& nodeToCompare) const {
  798. if (GetValuesCount() != nodeToCompare.GetValuesCount())
  799. return false;
  800. for (size_t i = 0; i < GetValuesCount(); ++i) {
  801. if (Values[i] != nodeToCompare.Values[i])
  802. return false;
  803. }
  804. return true;
  805. }
  806. TListType::TListType(TType* itemType, const TTypeEnvironment& env, bool validate)
  807. : TType(EKind::List, env.GetTypeOfTypeLazy(), itemType->IsPresortSupported())
  808. , Data(itemType)
  809. , IndexDictKey(env.GetUi64Lazy())
  810. {
  811. Y_UNUSED(validate);
  812. }
  813. TListType* TListType::Create(TType* itemType, const TTypeEnvironment& env) {
  814. return ::new(env.Allocate<TListType>()) TListType(itemType, env);
  815. }
  816. bool TListType::IsSameType(const TListType& typeToCompare) const {
  817. return GetItemType()->IsSameType(*typeToCompare.GetItemType());
  818. }
  819. size_t TListType::CalcHash() const {
  820. return CombineHashes(IndexDictKey->CalcHash(), Data->CalcHash());
  821. }
  822. bool TListType::IsConvertableTo(const TListType& typeToCompare, bool ignoreTagged) const {
  823. return GetItemType()->IsConvertableTo(*typeToCompare.GetItemType(), ignoreTagged);
  824. }
  825. void TListType::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  826. auto itemTypeIt = links.find(GetItemType());
  827. if (itemTypeIt != links.end()) {
  828. TNode* newNode = itemTypeIt->second;
  829. Y_DEBUG_ABORT_UNLESS(GetItemType()->Equals(*newNode));
  830. Data = static_cast<TType*>(newNode);
  831. }
  832. }
  833. TNode* TListType::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  834. auto newTypeNode = (TNode*)GetItemType()->GetCookie();
  835. if (!newTypeNode)
  836. return const_cast<TListType*>(this);
  837. return ::new(env.Allocate<TListType>()) TListType(static_cast<TType*>(newTypeNode), env, false);
  838. }
  839. void TListType::DoFreeze(const TTypeEnvironment& env) {
  840. Y_UNUSED(env);
  841. }
  842. TListLiteral::TListLiteral(TRuntimeNode* items, ui32 count, TListType* type, const TTypeEnvironment& env, bool validate)
  843. : TNode(type)
  844. , Items(items)
  845. , Count(count)
  846. {
  847. for (ui32 i = 0; i < count; ++i) {
  848. Y_DEBUG_ABORT_UNLESS(items[i].GetNode());
  849. }
  850. if (!validate) {
  851. TListLiteral::DoFreeze(env);
  852. return;
  853. }
  854. for (ui32 i = 0; i < Count; ++i) {
  855. auto& item = Items[i];
  856. MKQL_ENSURE(item.GetStaticType()->IsSameType(*type->GetItemType()), "Wrong type of item");
  857. }
  858. TListLiteral::DoFreeze(env);
  859. }
  860. TListLiteral* TListLiteral::Create(TRuntimeNode* items, ui32 count, TListType* type, const TTypeEnvironment& env) {
  861. TRuntimeNode* allocatedItems = nullptr;
  862. if (count) {
  863. allocatedItems = static_cast<TRuntimeNode*>(env.AllocateBuffer(count * sizeof(*allocatedItems)));
  864. for (ui32 i = 0; i < count; ++i) {
  865. allocatedItems[i] = items[i];
  866. }
  867. }
  868. return ::new(env.Allocate<TListLiteral>()) TListLiteral(allocatedItems, count, type, env);
  869. }
  870. void TListLiteral::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  871. auto typeIt = links.find(Type);
  872. if (typeIt != links.end()) {
  873. TNode* newNode = typeIt->second;
  874. Y_DEBUG_ABORT_UNLESS(Type->Equals(*newNode));
  875. Type = static_cast<TType*>(newNode);
  876. }
  877. for (ui32 i = 0; i < Count; ++i) {
  878. auto& item = Items[i];
  879. auto itemIt = links.find(item.GetNode());
  880. if (itemIt != links.end()) {
  881. TNode* newNode = itemIt->second;
  882. Y_DEBUG_ABORT_UNLESS(item.GetNode()->Equals(*newNode));
  883. item = TRuntimeNode(newNode, item.IsImmediate());
  884. }
  885. }
  886. }
  887. TNode* TListLiteral::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  888. auto newTypeNode = (TNode*)Type->GetCookie();
  889. bool needClone = false;
  890. if (newTypeNode) {
  891. needClone = true;
  892. } else {
  893. for (ui32 i = 0; i < Count; ++i) {
  894. if (Items[i].GetNode()->GetCookie()) {
  895. needClone = true;
  896. break;
  897. }
  898. }
  899. }
  900. if (!needClone)
  901. return const_cast<TListLiteral*>(this);
  902. TVector<TRuntimeNode> newList;
  903. newList.reserve(Count);
  904. for (ui32 i = 0; i < Count; ++i) {
  905. auto newNode = (TNode*)Items[i].GetNode()->GetCookie();
  906. if (newNode) {
  907. newList.push_back(TRuntimeNode(newNode, Items[i].IsImmediate()));
  908. } else {
  909. newList.push_back(Items[i]);
  910. }
  911. }
  912. TRuntimeNode* allocatedItems = nullptr;
  913. if (newList.size()) {
  914. allocatedItems = static_cast<TRuntimeNode*>(env.AllocateBuffer(newList.size() * sizeof(*allocatedItems)));
  915. for (ui32 i = 0; i < newList.size(); ++i) {
  916. allocatedItems[i] = newList[i];
  917. }
  918. }
  919. return ::new(env.Allocate<TListLiteral>()) TListLiteral(allocatedItems, newList.size(),
  920. newTypeNode ? static_cast<TListType*>(newTypeNode) : GetType(), env, false);
  921. }
  922. void TListLiteral::DoFreeze(const TTypeEnvironment&) {
  923. ui32 voidCount = 0;
  924. for (ui32 i = 0; i < Count; ++i) {
  925. auto& node = Items[i];
  926. node.Freeze();
  927. if (node.HasValue() && node.GetValue()->GetType()->IsVoid()) {
  928. ++voidCount;
  929. }
  930. }
  931. if (!voidCount)
  932. return;
  933. TRuntimeNode* newItems = Items;
  934. for (ui32 i = 0; i < Count; ++i) {
  935. auto node = Items[i];
  936. if (node.HasValue() && node.GetValue()->GetType()->IsVoid()) {
  937. continue;
  938. }
  939. *newItems++ = node;
  940. }
  941. Count = newItems - Items;
  942. }
  943. bool TListLiteral::Equals(const TListLiteral& nodeToCompare) const {
  944. if (Count != nodeToCompare.Count)
  945. return false;
  946. for (ui32 i = 0; i < Count; ++i) {
  947. if (Items[i] != nodeToCompare.Items[i])
  948. return false;
  949. }
  950. return true;
  951. }
  952. TStreamType::TStreamType(TType* itemType, const TTypeEnvironment& env, bool validate)
  953. : TType(EKind::Stream, env.GetTypeOfTypeLazy(), false)
  954. , Data(itemType)
  955. {
  956. Y_UNUSED(validate);
  957. }
  958. TStreamType* TStreamType::Create(TType* itemType, const TTypeEnvironment& env) {
  959. return ::new(env.Allocate<TStreamType>()) TStreamType(itemType, env);
  960. }
  961. bool TStreamType::IsSameType(const TStreamType& typeToCompare) const {
  962. return GetItemType()->IsSameType(*typeToCompare.GetItemType());
  963. }
  964. size_t TStreamType::CalcHash() const {
  965. return Data->CalcHash();
  966. }
  967. bool TStreamType::IsConvertableTo(const TStreamType& typeToCompare, bool ignoreTagged) const {
  968. return GetItemType()->IsConvertableTo(*typeToCompare.GetItemType(), ignoreTagged);
  969. }
  970. void TStreamType::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  971. auto itemTypeIt = links.find(GetItemType());
  972. if (itemTypeIt != links.end()) {
  973. TNode* newNode = itemTypeIt->second;
  974. Y_DEBUG_ABORT_UNLESS(GetItemType()->Equals(*newNode));
  975. Data = static_cast<TType*>(newNode);
  976. }
  977. }
  978. TNode* TStreamType::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  979. auto newTypeNode = (TNode*)GetItemType()->GetCookie();
  980. if (!newTypeNode)
  981. return const_cast<TStreamType*>(this);
  982. return ::new(env.Allocate<TStreamType>()) TStreamType(static_cast<TType*>(newTypeNode), env, false);
  983. }
  984. void TStreamType::DoFreeze(const TTypeEnvironment& env) {
  985. Y_UNUSED(env);
  986. }
  987. TFlowType::TFlowType(TType* itemType, const TTypeEnvironment& env, bool validate)
  988. : TType(EKind::Flow, env.GetTypeOfTypeLazy(), false)
  989. , Data(itemType)
  990. {
  991. Y_UNUSED(validate);
  992. }
  993. TFlowType* TFlowType::Create(TType* itemType, const TTypeEnvironment& env) {
  994. return ::new(env.Allocate<TFlowType>()) TFlowType(itemType, env);
  995. }
  996. bool TFlowType::IsSameType(const TFlowType& typeToCompare) const {
  997. return GetItemType()->IsSameType(*typeToCompare.GetItemType());
  998. }
  999. size_t TFlowType::CalcHash() const {
  1000. return Data->CalcHash();
  1001. }
  1002. bool TFlowType::IsConvertableTo(const TFlowType& typeToCompare, bool ignoreTagged) const {
  1003. return GetItemType()->IsConvertableTo(*typeToCompare.GetItemType(), ignoreTagged);
  1004. }
  1005. void TFlowType::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  1006. auto itemTypeIt = links.find(GetItemType());
  1007. if (itemTypeIt != links.end()) {
  1008. TNode* newNode = itemTypeIt->second;
  1009. Y_DEBUG_ABORT_UNLESS(GetItemType()->Equals(*newNode));
  1010. Data = static_cast<TType*>(newNode);
  1011. }
  1012. }
  1013. TNode* TFlowType::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  1014. auto newTypeNode = (TNode*)GetItemType()->GetCookie();
  1015. if (!newTypeNode)
  1016. return const_cast<TFlowType*>(this);
  1017. return ::new(env.Allocate<TFlowType>()) TFlowType(static_cast<TType*>(newTypeNode), env, false);
  1018. }
  1019. void TFlowType::DoFreeze(const TTypeEnvironment& env) {
  1020. Y_UNUSED(env);
  1021. }
  1022. TOptionalType::TOptionalType(TType* itemType, const TTypeEnvironment& env, bool validate)
  1023. : TType(EKind::Optional, env.GetTypeOfTypeLazy(), itemType->IsPresortSupported())
  1024. , Data(itemType)
  1025. {
  1026. Y_UNUSED(validate);
  1027. }
  1028. TOptionalType* TOptionalType::Create(TType* itemType, const TTypeEnvironment& env) {
  1029. return ::new(env.Allocate<TOptionalType>()) TOptionalType(itemType, env);
  1030. }
  1031. bool TOptionalType::IsSameType(const TOptionalType& typeToCompare) const {
  1032. return GetItemType()->IsSameType(*typeToCompare.GetItemType());
  1033. }
  1034. size_t TOptionalType::CalcHash() const {
  1035. return Data->CalcHash();
  1036. }
  1037. bool TOptionalType::IsConvertableTo(const TOptionalType& typeToCompare, bool ignoreTagged) const {
  1038. return GetItemType()->IsConvertableTo(*typeToCompare.GetItemType(), ignoreTagged);
  1039. }
  1040. void TOptionalType::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  1041. auto itemTypeIt = links.find(GetItemType());
  1042. if (itemTypeIt != links.end()) {
  1043. TNode* newNode = itemTypeIt->second;
  1044. Y_DEBUG_ABORT_UNLESS(GetItemType()->Equals(*newNode));
  1045. Data = static_cast<TType*>(newNode);
  1046. }
  1047. }
  1048. TNode* TOptionalType::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  1049. auto newTypeNode = (TNode*)GetItemType()->GetCookie();
  1050. if (!newTypeNode)
  1051. return const_cast<TOptionalType*>(this);
  1052. return ::new(env.Allocate<TOptionalType>()) TOptionalType(static_cast<TType*>(newTypeNode), env, false);
  1053. }
  1054. void TOptionalType::DoFreeze(const TTypeEnvironment& env) {
  1055. Y_UNUSED(env);
  1056. }
  1057. TTaggedType::TTaggedType(TType* baseType, TInternName tag, const TTypeEnvironment& env)
  1058. : TType(EKind::Tagged, env.GetTypeOfTypeLazy(), baseType->IsPresortSupported())
  1059. , BaseType(baseType)
  1060. , Tag(tag)
  1061. {
  1062. }
  1063. TTaggedType* TTaggedType::Create(TType* baseType, const TStringBuf& tag, const TTypeEnvironment& env) {
  1064. return ::new(env.Allocate<TTaggedType>()) TTaggedType(baseType, env.InternName(tag), env);
  1065. }
  1066. bool TTaggedType::IsSameType(const TTaggedType& typeToCompare) const {
  1067. return Tag == typeToCompare.Tag && GetBaseType()->IsSameType(*typeToCompare.GetBaseType());
  1068. }
  1069. size_t TTaggedType::CalcHash() const {
  1070. return CombineHashes(BaseType->CalcHash(), Tag.Hash());
  1071. }
  1072. bool TTaggedType::IsConvertableTo(const TTaggedType& typeToCompare, bool ignoreTagged) const {
  1073. return Tag == typeToCompare.Tag && GetBaseType()->IsConvertableTo(*typeToCompare.GetBaseType(), ignoreTagged);
  1074. }
  1075. void TTaggedType::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  1076. auto itemTypeIt = links.find(GetBaseType());
  1077. if (itemTypeIt != links.end()) {
  1078. TNode* newNode = itemTypeIt->second;
  1079. Y_DEBUG_ABORT_UNLESS(GetBaseType()->Equals(*newNode));
  1080. BaseType = static_cast<TType*>(newNode);
  1081. }
  1082. }
  1083. TNode* TTaggedType::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  1084. auto newTypeNode = (TNode*)GetBaseType()->GetCookie();
  1085. if (!newTypeNode)
  1086. return const_cast<TTaggedType*>(this);
  1087. return ::new(env.Allocate<TTaggedType>()) TTaggedType(static_cast<TType*>(newTypeNode), Tag, env);
  1088. }
  1089. void TTaggedType::DoFreeze(const TTypeEnvironment& env) {
  1090. Y_UNUSED(env);
  1091. }
  1092. TOptionalLiteral::TOptionalLiteral(TOptionalType* type, bool validate)
  1093. : TNode(type)
  1094. {
  1095. Y_UNUSED(validate);
  1096. }
  1097. TOptionalLiteral::TOptionalLiteral(TRuntimeNode item, TOptionalType* type, bool validate)
  1098. : TNode(type)
  1099. , Item(item)
  1100. {
  1101. if (!validate) {
  1102. Item.Freeze();
  1103. return;
  1104. }
  1105. Y_DEBUG_ABORT_UNLESS(Item.GetNode());
  1106. MKQL_ENSURE(Item.GetStaticType()->IsSameType(*type->GetItemType()), "Wrong type of item");
  1107. Item.Freeze();
  1108. }
  1109. TOptionalLiteral* TOptionalLiteral::Create(TOptionalType* type, const TTypeEnvironment& env) {
  1110. return ::new(env.Allocate<TOptionalLiteral>()) TOptionalLiteral(type);
  1111. }
  1112. TOptionalLiteral* TOptionalLiteral::Create(TRuntimeNode item, TOptionalType* type, const TTypeEnvironment& env) {
  1113. return ::new(env.Allocate<TOptionalLiteral>()) TOptionalLiteral(item, type);
  1114. }
  1115. void TOptionalLiteral::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  1116. auto typeIt = links.find(Type);
  1117. if (typeIt != links.end()) {
  1118. TNode* newNode = typeIt->second;
  1119. Y_DEBUG_ABORT_UNLESS(Type->Equals(*newNode));
  1120. Type = static_cast<TType*>(newNode);
  1121. }
  1122. if (Item.GetNode()) {
  1123. auto itemIt = links.find(Item.GetNode());
  1124. if (itemIt != links.end()) {
  1125. TNode* newNode = itemIt->second;
  1126. Y_DEBUG_ABORT_UNLESS(Item.GetNode()->Equals(*newNode));
  1127. Item = TRuntimeNode(newNode, Item.IsImmediate());
  1128. }
  1129. }
  1130. }
  1131. TNode* TOptionalLiteral::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  1132. auto newTypeNode = (TNode*)Type->GetCookie();
  1133. auto newItemNode = Item.GetNode() ? (TNode*)Item.GetNode()->GetCookie() : nullptr;
  1134. if (!newTypeNode && !newItemNode) {
  1135. return const_cast<TOptionalLiteral*>(this);
  1136. }
  1137. if (!Item.GetNode()) {
  1138. return ::new(env.Allocate<TOptionalLiteral>()) TOptionalLiteral(
  1139. newTypeNode ? static_cast<TOptionalType*>(newTypeNode) : GetType(), false);
  1140. } else {
  1141. return ::new(env.Allocate<TOptionalLiteral>()) TOptionalLiteral(
  1142. newItemNode ? TRuntimeNode(newItemNode, Item.IsImmediate()) : Item,
  1143. newTypeNode ? static_cast<TOptionalType*>(newTypeNode) : GetType(), false);
  1144. }
  1145. }
  1146. void TOptionalLiteral::DoFreeze(const TTypeEnvironment& env) {
  1147. Y_UNUSED(env);
  1148. if (Item.GetNode()) {
  1149. Item.Freeze();
  1150. }
  1151. }
  1152. bool TOptionalLiteral::Equals(const TOptionalLiteral& nodeToCompare) const {
  1153. if (!Item.GetNode() != !nodeToCompare.Item.GetNode())
  1154. return false;
  1155. return !Item.GetNode() || Item.GetNode()->Equals(*nodeToCompare.Item.GetNode());
  1156. }
  1157. TDictType* TDictType::Create(TType* keyType, TType* payloadType, const TTypeEnvironment& env) {
  1158. return ::new(env.Allocate<TDictType>()) TDictType(keyType, payloadType, env);
  1159. }
  1160. bool TDictType::IsSameType(const TDictType& typeToCompare) const {
  1161. return KeyType->IsSameType(*typeToCompare.KeyType)
  1162. && PayloadType->IsSameType(*typeToCompare.PayloadType);
  1163. }
  1164. size_t TDictType::CalcHash() const {
  1165. return CombineHashes(KeyType->CalcHash(), PayloadType->CalcHash());
  1166. }
  1167. bool TDictType::IsConvertableTo(const TDictType& typeToCompare, bool ignoreTagged) const {
  1168. return KeyType->IsConvertableTo(*typeToCompare.KeyType, ignoreTagged)
  1169. && PayloadType->IsConvertableTo(*typeToCompare.PayloadType, ignoreTagged);
  1170. }
  1171. void TDictType::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  1172. auto keyTypeIt = links.find(KeyType);
  1173. if (keyTypeIt != links.end()) {
  1174. TNode* newNode = keyTypeIt->second;
  1175. Y_DEBUG_ABORT_UNLESS(KeyType->Equals(*newNode));
  1176. KeyType = static_cast<TType*>(newNode);
  1177. }
  1178. auto payloadTypeIt = links.find(PayloadType);
  1179. if (payloadTypeIt != links.end()) {
  1180. TNode* newNode = payloadTypeIt->second;
  1181. Y_DEBUG_ABORT_UNLESS(PayloadType->Equals(*newNode));
  1182. PayloadType = static_cast<TType*>(newNode);
  1183. }
  1184. }
  1185. TNode* TDictType::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  1186. auto newKeyType = (TNode*)KeyType->GetCookie();
  1187. auto newPayloadType = (TNode*)PayloadType->GetCookie();
  1188. if (!newKeyType && !newPayloadType) {
  1189. return const_cast<TDictType*>(this);
  1190. }
  1191. return ::new(env.Allocate<TDictType>()) TDictType(
  1192. newKeyType ? static_cast<TType*>(newKeyType) : KeyType,
  1193. newPayloadType ? static_cast<TType*>(newPayloadType) : PayloadType, env, false);
  1194. }
  1195. void TDictType::DoFreeze(const TTypeEnvironment& env) {
  1196. Y_UNUSED(env);
  1197. }
  1198. TDictType::TDictType(TType* keyType, TType* payloadType, const TTypeEnvironment& env, bool validate)
  1199. : TType(EKind::Dict, env.GetTypeOfTypeLazy(), keyType->IsPresortSupported() && payloadType->IsPresortSupported())
  1200. , KeyType(keyType)
  1201. , PayloadType(payloadType)
  1202. {
  1203. if (!validate)
  1204. return;
  1205. EnsureValidDictKey(keyType);
  1206. }
  1207. void TDictType::EnsureValidDictKey(TType* keyType) {
  1208. Y_UNUSED(keyType);
  1209. }
  1210. TDictLiteral::TDictLiteral(ui32 itemsCount, std::pair<TRuntimeNode, TRuntimeNode>* items, TDictType* type, bool validate)
  1211. : TNode(type)
  1212. , ItemsCount(itemsCount)
  1213. , Items(items)
  1214. {
  1215. if (!validate) {
  1216. for (size_t index = 0; index < itemsCount; ++index) {
  1217. auto& item = Items[index];
  1218. item.first.Freeze();
  1219. item.second.Freeze();
  1220. }
  1221. return;
  1222. }
  1223. for (size_t index = 0; index < itemsCount; ++index) {
  1224. auto& item = Items[index];
  1225. MKQL_ENSURE(item.first.GetStaticType()->IsSameType(*type->GetKeyType()), "Wrong type of key");
  1226. MKQL_ENSURE(item.second.GetStaticType()->IsSameType(*type->GetPayloadType()), "Wrong type of payload");
  1227. item.first.Freeze();
  1228. item.second.Freeze();
  1229. }
  1230. }
  1231. TDictLiteral* TDictLiteral::Create(ui32 itemsCount, const std::pair<TRuntimeNode, TRuntimeNode>* items, TDictType* type,
  1232. const TTypeEnvironment& env) {
  1233. std::pair<TRuntimeNode, TRuntimeNode>* allocatedItems = nullptr;
  1234. if (itemsCount) {
  1235. allocatedItems = static_cast<std::pair<TRuntimeNode, TRuntimeNode>*>(env.AllocateBuffer(itemsCount * sizeof(*allocatedItems)));
  1236. for (ui32 i = 0; i < itemsCount; ++i) {
  1237. allocatedItems[i] = items[i];
  1238. }
  1239. }
  1240. return ::new(env.Allocate<TDictLiteral>()) TDictLiteral(itemsCount, allocatedItems, type);
  1241. }
  1242. void TDictLiteral::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  1243. auto typeIt = links.find(Type);
  1244. if (typeIt != links.end()) {
  1245. TNode* newNode = typeIt->second;
  1246. Y_DEBUG_ABORT_UNLESS(Type->Equals(*newNode));
  1247. Type = static_cast<TType*>(newNode);
  1248. }
  1249. for (ui32 i = 0; i < ItemsCount; ++i) {
  1250. auto& item = Items[i];
  1251. auto itemKeyIt = links.find(item.first.GetNode());
  1252. if (itemKeyIt != links.end()) {
  1253. TNode* newNode = itemKeyIt->second;
  1254. Y_DEBUG_ABORT_UNLESS(item.first.GetNode()->Equals(*newNode));
  1255. item.first = TRuntimeNode(newNode, item.first.IsImmediate());
  1256. }
  1257. auto itemPayloadIt = links.find(item.second.GetNode());
  1258. if (itemPayloadIt != links.end()) {
  1259. TNode* newNode = itemPayloadIt->second;
  1260. Y_DEBUG_ABORT_UNLESS(item.second.GetNode()->Equals(*newNode));
  1261. item.second = TRuntimeNode(newNode, item.second.IsImmediate());
  1262. }
  1263. }
  1264. }
  1265. TNode* TDictLiteral::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  1266. auto newTypeNode = (TNode*)Type->GetCookie();
  1267. bool needClone = false;
  1268. if (newTypeNode) {
  1269. needClone = true;
  1270. } else {
  1271. for (ui32 i = 0; i < ItemsCount; ++i) {
  1272. if (Items[i].first.GetNode()->GetCookie()) {
  1273. needClone = true;
  1274. break;
  1275. }
  1276. if (Items[i].second.GetNode()->GetCookie()) {
  1277. needClone = true;
  1278. break;
  1279. }
  1280. }
  1281. }
  1282. if (!needClone)
  1283. return const_cast<TDictLiteral*>(this);
  1284. std::pair<TRuntimeNode, TRuntimeNode>* allocatedItems = nullptr;
  1285. if (ItemsCount) {
  1286. allocatedItems = static_cast<std::pair<TRuntimeNode, TRuntimeNode>*>(env.AllocateBuffer(ItemsCount * sizeof(*allocatedItems)));
  1287. for (ui32 i = 0; i < ItemsCount; ++i) {
  1288. allocatedItems[i] = Items[i];
  1289. auto newKeyNode = (TNode*)Items[i].first.GetNode()->GetCookie();
  1290. if (newKeyNode) {
  1291. allocatedItems[i].first = TRuntimeNode(newKeyNode, Items[i].first.IsImmediate());
  1292. }
  1293. auto newPayloadNode = (TNode*)Items[i].second.GetNode()->GetCookie();
  1294. if (newPayloadNode) {
  1295. allocatedItems[i].second = TRuntimeNode(newPayloadNode, Items[i].second.IsImmediate());
  1296. }
  1297. }
  1298. }
  1299. return ::new(env.Allocate<TDictLiteral>()) TDictLiteral(ItemsCount, allocatedItems,
  1300. newTypeNode ? static_cast<TDictType*>(newTypeNode) : GetType(), false);
  1301. }
  1302. void TDictLiteral::DoFreeze(const TTypeEnvironment& env) {
  1303. Y_UNUSED(env);
  1304. for (ui32 i = 0; i < ItemsCount; ++i) {
  1305. Items[i].first.Freeze();
  1306. Items[i].second.Freeze();
  1307. }
  1308. }
  1309. bool TDictLiteral::Equals(const TDictLiteral& nodeToCompare) const {
  1310. if (ItemsCount != nodeToCompare.ItemsCount)
  1311. return false;
  1312. for (size_t i = 0; i < ItemsCount; ++i) {
  1313. if (Items[i] != nodeToCompare.Items[i])
  1314. return false;
  1315. }
  1316. return true;
  1317. }
  1318. TCallableType::TCallableType(const TInternName &name, TType* returnType, ui32 argumentsCount,
  1319. TType **arguments, TNode* payload, const TTypeEnvironment& env)
  1320. : TType(EKind::Callable, env.GetTypeOfTypeLazy(), false)
  1321. , IsMergeDisabled0(false)
  1322. , ArgumentsCount(argumentsCount)
  1323. , Name(name)
  1324. , ReturnType(returnType)
  1325. , Arguments(arguments)
  1326. , Payload(payload)
  1327. , OptionalArgs(0)
  1328. {
  1329. }
  1330. TCallableType* TCallableType::Create(const TString& name, TType* returnType,
  1331. ui32 argumentsCount, TType** arguments, TNode* payload, const TTypeEnvironment& env) {
  1332. auto internedName = env.InternName(name);
  1333. TType** allocatedArguments = nullptr;
  1334. if (argumentsCount) {
  1335. allocatedArguments = static_cast<TType**>(env.AllocateBuffer(argumentsCount * sizeof(*allocatedArguments)));
  1336. for (ui32 i = 0; i < argumentsCount; ++i) {
  1337. allocatedArguments[i] = arguments[i];
  1338. }
  1339. }
  1340. return ::new(env.Allocate<TCallableType>()) TCallableType(internedName, returnType, argumentsCount,
  1341. allocatedArguments, payload, env);
  1342. }
  1343. TCallableType* TCallableType::Create(TType* returnType, const TStringBuf& name, ui32 argumentsCount,
  1344. TType** arguments, TNode* payload, const TTypeEnvironment& env) {
  1345. auto internedName = env.InternName(name);
  1346. TType** allocatedArguments = nullptr;
  1347. if (argumentsCount) {
  1348. allocatedArguments = static_cast<TType**>(env.AllocateBuffer(argumentsCount * sizeof(*allocatedArguments)));
  1349. for (ui32 i = 0; i < argumentsCount; ++i) {
  1350. allocatedArguments[i] = arguments[i];
  1351. }
  1352. }
  1353. return ::new(env.Allocate<TCallableType>()) TCallableType(internedName, returnType, argumentsCount,
  1354. allocatedArguments, payload, env);
  1355. }
  1356. bool TCallableType::IsSameType(const TCallableType& typeToCompare) const {
  1357. if (this == &typeToCompare)
  1358. return true;
  1359. if (Name != typeToCompare.Name || IsMergeDisabled0 != typeToCompare.IsMergeDisabled0)
  1360. return false;
  1361. if (ArgumentsCount != typeToCompare.ArgumentsCount)
  1362. return false;
  1363. if (OptionalArgs != typeToCompare.OptionalArgs)
  1364. return false;
  1365. for (size_t index = 0; index < ArgumentsCount; ++index) {
  1366. const auto arg = Arguments[index];
  1367. const auto otherArg = typeToCompare.Arguments[index];
  1368. if (!arg->IsSameType(*otherArg))
  1369. return false;
  1370. }
  1371. if (!ReturnType->IsSameType(*typeToCompare.ReturnType))
  1372. return false;
  1373. if (!Payload != !typeToCompare.Payload)
  1374. return false;
  1375. return !Payload || Payload->Equals(*typeToCompare.Payload);
  1376. }
  1377. size_t TCallableType::CalcHash() const {
  1378. size_t hash = 0;
  1379. hash = CombineHashes(hash, IntHash<size_t>(ArgumentsCount));
  1380. hash = CombineHashes(hash, Name.Hash());
  1381. hash = CombineHashes(hash, ReturnType->CalcHash());
  1382. for (size_t index = 0; index < ArgumentsCount; ++index) {
  1383. hash = CombineHashes(hash, Arguments[index]->CalcHash());
  1384. }
  1385. hash = CombineHashes(hash, IntHash<size_t>(OptionalArgs));
  1386. return hash;
  1387. }
  1388. bool TCallableType::IsConvertableTo(const TCallableType& typeToCompare, bool ignoreTagged) const {
  1389. // do not check callable name here
  1390. if (this == &typeToCompare)
  1391. return true;
  1392. if (IsMergeDisabled0 != typeToCompare.IsMergeDisabled0)
  1393. return false;
  1394. if (ArgumentsCount < typeToCompare.ArgumentsCount)
  1395. return false;
  1396. // function with fewer optional args can't be converted to function
  1397. // with more optional args
  1398. if (ArgumentsCount - OptionalArgs > typeToCompare.ArgumentsCount - typeToCompare.OptionalArgs)
  1399. return false;
  1400. for (size_t index = 0; index < typeToCompare.ArgumentsCount; ++index) {
  1401. const auto arg = Arguments[index];
  1402. const auto otherArg = typeToCompare.Arguments[index];
  1403. if (!arg->IsConvertableTo(*otherArg, ignoreTagged))
  1404. return false;
  1405. }
  1406. if (!ReturnType->IsConvertableTo(*typeToCompare.ReturnType, ignoreTagged))
  1407. return false;
  1408. if (!Payload) {
  1409. return true;
  1410. }
  1411. if (!typeToCompare.Payload) {
  1412. return false;
  1413. }
  1414. TCallablePayload parsedPayload(Payload), parsedPayloadToCompare(typeToCompare.Payload);
  1415. for (size_t index = 0; index < typeToCompare.ArgumentsCount; ++index) {
  1416. if (parsedPayload.GetArgumentName(index) != parsedPayloadToCompare.GetArgumentName(index)) {
  1417. return false;
  1418. }
  1419. if (parsedPayload.GetArgumentFlags(index) != parsedPayloadToCompare.GetArgumentFlags(index)) {
  1420. return false;
  1421. }
  1422. }
  1423. return true;
  1424. }
  1425. void TCallableType::SetOptionalArgumentsCount(ui32 count) {
  1426. MKQL_ENSURE(count <= ArgumentsCount, "Wrong optional arguments count: " << count << ", function has only " <<
  1427. ArgumentsCount << " arguments");
  1428. OptionalArgs = count;
  1429. for (ui32 index = ArgumentsCount - OptionalArgs; index < ArgumentsCount; ++index) {
  1430. MKQL_ENSURE(Arguments[index]->IsOptional(), "Optional argument #" << (index + 1) << " must be an optional");
  1431. }
  1432. }
  1433. void TCallableType::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  1434. auto returnTypeIt = links.find(ReturnType);
  1435. if (returnTypeIt != links.end()) {
  1436. TNode* newNode = returnTypeIt->second;
  1437. Y_DEBUG_ABORT_UNLESS(ReturnType->Equals(*newNode));
  1438. ReturnType = static_cast<TType*>(newNode);
  1439. }
  1440. for (ui32 i = 0; i < ArgumentsCount; ++i) {
  1441. auto& arg = Arguments[i];
  1442. auto argIt = links.find(arg);
  1443. if (argIt != links.end()) {
  1444. TNode* newNode = argIt->second;
  1445. Y_DEBUG_ABORT_UNLESS(arg->Equals(*newNode));
  1446. arg = static_cast<TType*>(newNode);
  1447. }
  1448. }
  1449. if (Payload) {
  1450. auto payloadIt = links.find(Payload);
  1451. if (payloadIt != links.end()) {
  1452. TNode* newNode = payloadIt->second;
  1453. Y_DEBUG_ABORT_UNLESS(Payload->Equals(*newNode));
  1454. Payload = newNode;
  1455. }
  1456. }
  1457. }
  1458. TNode* TCallableType::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  1459. auto newReturnTypeNode = (TNode*)ReturnType->GetCookie();
  1460. auto newPayloadNode = Payload ? (TNode*)Payload->GetCookie() : nullptr;
  1461. bool needClone = false;
  1462. if (newReturnTypeNode || newPayloadNode) {
  1463. needClone = true;
  1464. } else {
  1465. for (ui32 i = 0; i < ArgumentsCount; ++i) {
  1466. if (Arguments[i]->GetCookie()) {
  1467. needClone = true;
  1468. break;
  1469. }
  1470. }
  1471. }
  1472. if (!needClone)
  1473. return const_cast<TCallableType*>(this);
  1474. TType** allocatedArguments = nullptr;
  1475. if (ArgumentsCount) {
  1476. allocatedArguments = static_cast<TType**>(env.AllocateBuffer(ArgumentsCount * sizeof(*allocatedArguments)));
  1477. for (ui32 i = 0; i < ArgumentsCount; ++i) {
  1478. allocatedArguments[i] = Arguments[i];
  1479. auto newArgNode = (TNode*)Arguments[i]->GetCookie();
  1480. if (newArgNode) {
  1481. allocatedArguments[i] = static_cast<TType*>(newArgNode);
  1482. }
  1483. }
  1484. }
  1485. return ::new(env.Allocate<TCallableType>()) TCallableType(Name,
  1486. newReturnTypeNode ? static_cast<TType*>(newReturnTypeNode) : ReturnType,
  1487. ArgumentsCount, allocatedArguments, newPayloadNode ? newPayloadNode : Payload, env);
  1488. }
  1489. void TCallableType::DoFreeze(const TTypeEnvironment& env) {
  1490. Y_UNUSED(env);
  1491. }
  1492. TCallable::TCallable(ui32 inputsCount, TRuntimeNode* inputs, TCallableType* type, bool validate)
  1493. : TNode(type)
  1494. , InputsCount(inputsCount)
  1495. , UniqueId(0)
  1496. , Inputs(inputs)
  1497. {
  1498. if (!validate) {
  1499. for (size_t index = 0; index < inputsCount; ++index) {
  1500. auto& node = Inputs[index];
  1501. node.Freeze();
  1502. }
  1503. return;
  1504. }
  1505. MKQL_ENSURE(inputsCount == type->GetArgumentsCount(), "Wrong count of inputs");
  1506. for (size_t index = 0; index < inputsCount; ++index) {
  1507. auto& node = Inputs[index];
  1508. const auto argType = type->GetArgumentType(index);
  1509. MKQL_ENSURE(node.GetStaticType()->IsSameType(*argType), "Wrong type of input");
  1510. node.Freeze();
  1511. }
  1512. }
  1513. TCallable::TCallable(TRuntimeNode result, TCallableType* type, bool validate)
  1514. : TNode(type)
  1515. , InputsCount(0)
  1516. , UniqueId(0)
  1517. , Inputs(nullptr)
  1518. , Result(result)
  1519. {
  1520. if (!validate) {
  1521. Result.Freeze();
  1522. return;
  1523. }
  1524. MKQL_ENSURE(result.GetStaticType()->IsSameType(*type->GetReturnType()), "incorrect result type for callable: "
  1525. << GetType()->GetName());
  1526. Result.Freeze();
  1527. }
  1528. TCallable* TCallable::Create(ui32 inputsCount, const TRuntimeNode* inputs, TCallableType* type, const TTypeEnvironment& env) {
  1529. TRuntimeNode* allocatedInputs = nullptr;
  1530. if (inputsCount) {
  1531. allocatedInputs = static_cast<TRuntimeNode*>(env.AllocateBuffer(inputsCount * sizeof(*allocatedInputs)));
  1532. for (ui32 i = 0; i < inputsCount; ++i) {
  1533. allocatedInputs[i] = inputs[i];
  1534. }
  1535. }
  1536. return ::new(env.Allocate<TCallable>()) TCallable(inputsCount, allocatedInputs, type);
  1537. }
  1538. TCallable* TCallable::Create(TRuntimeNode result, TCallableType* type, const TTypeEnvironment& env) {
  1539. return ::new(env.Allocate<TCallable>()) TCallable(result, type);
  1540. }
  1541. void TCallable::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  1542. auto typeIt = links.find(Type);
  1543. if (typeIt != links.end()) {
  1544. TNode* newNode = typeIt->second;
  1545. Y_DEBUG_ABORT_UNLESS(Type->Equals(*newNode));
  1546. Type = static_cast<TType*>(newNode);
  1547. }
  1548. for (ui32 i = 0; i < InputsCount; ++i) {
  1549. auto& input = Inputs[i];
  1550. auto inputIt = links.find(input.GetNode());
  1551. if (inputIt != links.end()) {
  1552. TNode* newNode = inputIt->second;
  1553. Y_DEBUG_ABORT_UNLESS(input.GetNode()->Equals(*newNode));
  1554. input = TRuntimeNode(newNode, input.IsImmediate());
  1555. }
  1556. }
  1557. if (Result.GetNode()) {
  1558. auto resultIt = links.find(Result.GetNode());
  1559. if (resultIt != links.end()) {
  1560. TNode* newNode = resultIt->second;
  1561. Y_DEBUG_ABORT_UNLESS(Result.GetNode()->Equals(*newNode));
  1562. Result = TRuntimeNode(newNode, Result.IsImmediate());
  1563. }
  1564. }
  1565. }
  1566. TNode* TCallable::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  1567. auto newTypeNode = (TNode*)Type->GetCookie();
  1568. auto newResultNode = Result.GetNode() ? (TNode*)Result.GetNode()->GetCookie() : nullptr;
  1569. bool needClone = false;
  1570. if (newTypeNode || newResultNode) {
  1571. needClone = true;
  1572. } else {
  1573. for (ui32 i = 0; i < InputsCount; ++i) {
  1574. if (Inputs[i].GetNode()->GetCookie()) {
  1575. needClone = true;
  1576. break;
  1577. }
  1578. }
  1579. }
  1580. if (!needClone)
  1581. return const_cast<TCallable*>(this);
  1582. TRuntimeNode* allocatedInputs = nullptr;
  1583. if (!Result.GetNode()) {
  1584. if (InputsCount) {
  1585. allocatedInputs = static_cast<TRuntimeNode*>(env.AllocateBuffer(InputsCount * sizeof(*allocatedInputs)));
  1586. for (ui32 i = 0; i < InputsCount; ++i) {
  1587. allocatedInputs[i] = Inputs[i];
  1588. auto newNode = (TNode*)Inputs[i].GetNode()->GetCookie();
  1589. if (newNode) {
  1590. allocatedInputs[i] = TRuntimeNode(newNode, Inputs[i].IsImmediate());
  1591. }
  1592. }
  1593. }
  1594. }
  1595. TCallable* newCallable;
  1596. if (Result.GetNode()) {
  1597. newCallable = ::new(env.Allocate<TCallable>()) TCallable(
  1598. newResultNode ? TRuntimeNode(newResultNode, Result.IsImmediate()) : Result,
  1599. newTypeNode ? static_cast<TCallableType*>(newTypeNode) : GetType(), false);
  1600. } else {
  1601. newCallable = ::new(env.Allocate<TCallable>()) TCallable(InputsCount, allocatedInputs,
  1602. newTypeNode ? static_cast<TCallableType*>(newTypeNode) : GetType(), false);
  1603. }
  1604. newCallable->SetUniqueId(GetUniqueId());
  1605. return newCallable;
  1606. }
  1607. void TCallable::DoFreeze(const TTypeEnvironment& env) {
  1608. Y_UNUSED(env);
  1609. for (ui32 i = 0; i < InputsCount; ++i) {
  1610. Inputs[i].Freeze();
  1611. }
  1612. }
  1613. bool TCallable::Equals(const TCallable& nodeToCompare) const {
  1614. if (GetType()->IsMergeDisabled() && (this != &nodeToCompare))
  1615. return false;
  1616. if (InputsCount != nodeToCompare.InputsCount)
  1617. return false;
  1618. if (!Result.GetNode() != !nodeToCompare.Result.GetNode())
  1619. return false;
  1620. for (size_t i = 0; i < InputsCount; ++i) {
  1621. if (Inputs[i] != nodeToCompare.Inputs[i])
  1622. return false;
  1623. }
  1624. if (Result.GetNode() && Result != nodeToCompare.Result)
  1625. return false;
  1626. return true;
  1627. }
  1628. void TCallable::SetResult(TRuntimeNode result, const TTypeEnvironment& env) {
  1629. Y_UNUSED(env);
  1630. MKQL_ENSURE(!Result.GetNode(), "result is already set");
  1631. MKQL_ENSURE(result.GetStaticType()->IsSameType(*GetType()->GetReturnType()),
  1632. "incorrect result type of function " << GetType()->GetName()
  1633. << ", left: " << PrintNode(result.GetStaticType(), true)
  1634. << ", right: " << PrintNode(GetType()->GetReturnType(), true));
  1635. Result = result;
  1636. InputsCount = 0;
  1637. Inputs = nullptr;
  1638. Result.Freeze();
  1639. }
  1640. TCallablePayload::TCallablePayload(NMiniKQL::TNode* node)
  1641. {
  1642. auto structObj = AS_VALUE(NMiniKQL::TStructLiteral, NMiniKQL::TRuntimeNode(node, true));
  1643. auto argsIndex = structObj->GetType()->GetMemberIndex("Args");
  1644. auto payloadIndex = structObj->GetType()->GetMemberIndex("Payload");
  1645. Payload_ = AS_VALUE(NMiniKQL::TDataLiteral, structObj->GetValue(payloadIndex))->AsValue().AsStringRef();
  1646. auto args = structObj->GetValue(argsIndex);
  1647. auto argsList = AS_VALUE(NMiniKQL::TListLiteral, args);
  1648. auto itemType = AS_TYPE(NMiniKQL::TStructType, AS_TYPE(NMiniKQL::TListType, args)->GetItemType());
  1649. auto nameIndex = itemType->GetMemberIndex("Name");
  1650. auto flagsIndex = itemType->GetMemberIndex("Flags");
  1651. ArgsNames_.reserve(argsList->GetItemsCount());
  1652. ArgsFlags_.reserve(argsList->GetItemsCount());
  1653. for (ui32 i = 0; i < argsList->GetItemsCount(); ++i) {
  1654. auto arg = AS_VALUE(NMiniKQL::TStructLiteral, argsList->GetItems()[i]);
  1655. ArgsNames_.push_back(AS_VALUE(NMiniKQL::TDataLiteral, arg->GetValue(nameIndex))->AsValue().AsStringRef());
  1656. ArgsFlags_.push_back(AS_VALUE(NMiniKQL::TDataLiteral, arg->GetValue(flagsIndex))->AsValue().Get<ui64>());
  1657. }
  1658. }
  1659. bool TRuntimeNode::HasValue() const {
  1660. TRuntimeNode current = *this;
  1661. for (;;) {
  1662. if (current.IsImmediate())
  1663. return true;
  1664. MKQL_ENSURE(current.GetNode()->GetType()->IsCallable(), "Wrong type");
  1665. const auto& callable = static_cast<const TCallable&>(*current.GetNode());
  1666. if (!callable.HasResult())
  1667. return false;
  1668. current = callable.GetResult();
  1669. }
  1670. }
  1671. TNode* TRuntimeNode::GetValue() const {
  1672. TRuntimeNode current = *this;
  1673. for (;;) {
  1674. if (current.IsImmediate())
  1675. return current.GetNode();
  1676. MKQL_ENSURE(current.GetNode()->GetType()->IsCallable(), "Wrong type");
  1677. const auto& callable = static_cast<const TCallable&>(*current.GetNode());
  1678. current = callable.GetResult();
  1679. }
  1680. }
  1681. void TRuntimeNode::Freeze() {
  1682. while (!IsImmediate()) {
  1683. MKQL_ENSURE(GetNode()->GetType()->IsCallable(), "Wrong type");
  1684. const auto& callable = static_cast<const TCallable&>(*GetNode());
  1685. if (!callable.HasResult())
  1686. break;
  1687. *this = callable.GetResult();
  1688. }
  1689. }
  1690. bool TAnyType::IsSameType(const TAnyType& typeToCompare) const {
  1691. Y_UNUSED(typeToCompare);
  1692. return true;
  1693. }
  1694. size_t TAnyType::CalcHash() const {
  1695. return 0;
  1696. }
  1697. bool TAnyType::IsConvertableTo(const TAnyType& typeToCompare, bool ignoreTagged) const {
  1698. Y_UNUSED(ignoreTagged);
  1699. return IsSameType(typeToCompare);
  1700. }
  1701. void TAnyType::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  1702. Y_UNUSED(links);
  1703. }
  1704. TNode* TAnyType::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  1705. Y_UNUSED(env);
  1706. return const_cast<TAnyType*>(this);
  1707. }
  1708. void TAnyType::DoFreeze(const TTypeEnvironment& env) {
  1709. Y_UNUSED(env);
  1710. }
  1711. TAnyType* TAnyType::Create(TTypeType* type, const TTypeEnvironment& env) {
  1712. return ::new(env.Allocate<TAnyType>()) TAnyType(type);
  1713. }
  1714. TAny* TAny::Create(const TTypeEnvironment& env) {
  1715. return ::new(env.Allocate<TAny>()) TAny(env.GetAnyTypeLazy());
  1716. }
  1717. void TAny::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  1718. if (Item.GetNode()) {
  1719. auto itemIt = links.find(Item.GetNode());
  1720. if (itemIt != links.end()) {
  1721. TNode* newNode = itemIt->second;
  1722. Y_DEBUG_ABORT_UNLESS(Item.GetNode()->Equals(*newNode));
  1723. Item = TRuntimeNode(newNode, Item.IsImmediate());
  1724. }
  1725. }
  1726. }
  1727. TNode* TAny::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  1728. if (!Item.GetNode())
  1729. return const_cast<TAny*>(this);
  1730. auto newItemNode = (TNode*)Item.GetNode()->GetCookie();
  1731. if (!newItemNode) {
  1732. return const_cast<TAny*>(this);
  1733. }
  1734. auto any = TAny::Create(env);
  1735. any->SetItem(TRuntimeNode(newItemNode, Item.IsImmediate()));
  1736. return any;
  1737. }
  1738. void TAny::DoFreeze(const TTypeEnvironment& env) {
  1739. Y_UNUSED(env);
  1740. if (Item.GetNode()) {
  1741. Item.Freeze();
  1742. }
  1743. }
  1744. void TAny::SetItem(TRuntimeNode newItem) {
  1745. MKQL_ENSURE(!Item.GetNode(), "item is already set");
  1746. Item = newItem;
  1747. Item.Freeze();
  1748. }
  1749. bool TAny::Equals(const TAny& nodeToCompare) const {
  1750. if (!Item.GetNode() || !nodeToCompare.Item.GetNode())
  1751. return false;
  1752. if (!Item.IsImmediate() != !nodeToCompare.Item.IsImmediate())
  1753. return false;
  1754. return Item.GetNode()->Equals(*nodeToCompare.Item.GetNode());
  1755. }
  1756. TTupleLiteral::TTupleLiteral(TRuntimeNode* values, TTupleType* type, bool validate)
  1757. : TNode(type)
  1758. , Values(values)
  1759. {
  1760. if (!validate) {
  1761. for (size_t index = 0; index < GetValuesCount(); ++index) {
  1762. auto& value = Values[index];
  1763. value.Freeze();
  1764. }
  1765. return;
  1766. }
  1767. for (size_t index = 0; index < GetValuesCount(); ++index) {
  1768. auto& value = Values[index];
  1769. MKQL_ENSURE(value.GetStaticType()->IsSameType(*type->GetElementType(index)), "Wrong type of element");
  1770. value.Freeze();
  1771. }
  1772. }
  1773. TTupleLiteral* TTupleLiteral::Create(ui32 valuesCount, const TRuntimeNode* values, TTupleType* type, const TTypeEnvironment& env, bool useCachedEmptyTuple) {
  1774. MKQL_ENSURE(valuesCount == type->GetElementsCount(), "Wrong count of elements");
  1775. TRuntimeNode* allocatedValues = nullptr;
  1776. if (valuesCount) {
  1777. allocatedValues = static_cast<TRuntimeNode*>(env.AllocateBuffer(valuesCount * sizeof(*allocatedValues)));
  1778. for (ui32 i = 0; i < valuesCount; ++i) {
  1779. allocatedValues[i] = values[i];
  1780. }
  1781. } else if (useCachedEmptyTuple) {
  1782. return env.GetEmptyTupleLazy();
  1783. }
  1784. return ::new(env.Allocate<TTupleLiteral>()) TTupleLiteral(allocatedValues, type);
  1785. }
  1786. void TTupleLiteral::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  1787. auto typeIt = links.find(Type);
  1788. if (typeIt != links.end()) {
  1789. TNode* newNode = typeIt->second;
  1790. Y_DEBUG_ABORT_UNLESS(Type->Equals(*newNode));
  1791. Type = static_cast<TType*>(newNode);
  1792. }
  1793. for (ui32 i = 0; i < GetValuesCount(); ++i) {
  1794. auto& value = Values[i];
  1795. auto valueIt = links.find(value.GetNode());
  1796. if (valueIt != links.end()) {
  1797. TNode* newNode = valueIt->second;
  1798. Y_DEBUG_ABORT_UNLESS(value.GetNode()->Equals(*newNode));
  1799. value = TRuntimeNode(newNode, value.IsImmediate());
  1800. }
  1801. }
  1802. }
  1803. TNode* TTupleLiteral::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  1804. auto newTypeNode = (TNode*)Type->GetCookie();
  1805. bool needClone = false;
  1806. if (newTypeNode) {
  1807. needClone = true;
  1808. } else {
  1809. for (ui32 i = 0; i < GetValuesCount(); ++i) {
  1810. if (Values[i].GetNode()->GetCookie()) {
  1811. needClone = true;
  1812. break;
  1813. }
  1814. }
  1815. }
  1816. if (!needClone)
  1817. return const_cast<TTupleLiteral*>(this);
  1818. TRuntimeNode* allocatedValues = nullptr;
  1819. if (GetValuesCount()) {
  1820. allocatedValues = static_cast<TRuntimeNode*>(env.AllocateBuffer(GetValuesCount() * sizeof(*allocatedValues)));
  1821. for (ui32 i = 0; i < GetValuesCount(); ++i) {
  1822. allocatedValues[i] = Values[i];
  1823. auto newNode = (TNode*)Values[i].GetNode()->GetCookie();
  1824. if (newNode) {
  1825. allocatedValues[i] = TRuntimeNode(newNode, Values[i].IsImmediate());
  1826. }
  1827. }
  1828. }
  1829. return ::new(env.Allocate<TTupleLiteral>()) TTupleLiteral(allocatedValues,
  1830. newTypeNode ? static_cast<TTupleType*>(newTypeNode) : GetType(), false);
  1831. }
  1832. void TTupleLiteral::DoFreeze(const TTypeEnvironment& env) {
  1833. Y_UNUSED(env);
  1834. for (ui32 i = 0; i < GetValuesCount(); ++i) {
  1835. Values[i].Freeze();
  1836. }
  1837. }
  1838. bool TTupleLiteral::Equals(const TTupleLiteral& nodeToCompare) const {
  1839. if (GetValuesCount() != nodeToCompare.GetValuesCount())
  1840. return false;
  1841. for (size_t i = 0; i < GetValuesCount(); ++i) {
  1842. if (Values[i] != nodeToCompare.Values[i])
  1843. return false;
  1844. }
  1845. return true;
  1846. }
  1847. bool TResourceType::IsSameType(const TResourceType& typeToCompare) const {
  1848. return Tag == typeToCompare.Tag;
  1849. }
  1850. size_t TResourceType::CalcHash() const {
  1851. return Tag.Hash();
  1852. }
  1853. bool TResourceType::IsConvertableTo(const TResourceType& typeToCompare, bool ignoreTagged) const {
  1854. Y_UNUSED(ignoreTagged);
  1855. return IsSameType(typeToCompare);
  1856. }
  1857. void TResourceType::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  1858. Y_UNUSED(links);
  1859. }
  1860. TNode* TResourceType::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  1861. Y_UNUSED(env);
  1862. return const_cast<TResourceType*>(this);
  1863. }
  1864. void TResourceType::DoFreeze(const TTypeEnvironment& env) {
  1865. Y_UNUSED(env);
  1866. }
  1867. TResourceType* TResourceType::Create(const TStringBuf& tag, const TTypeEnvironment& env) {
  1868. return ::new(env.Allocate<TResourceType>()) TResourceType(env.GetTypeOfTypeLazy(), env.InternName(tag));
  1869. }
  1870. TVariantType* TVariantType::Create(TType* underlyingType, const TTypeEnvironment& env) {
  1871. return ::new(env.Allocate<TVariantType>()) TVariantType(underlyingType, env);
  1872. }
  1873. bool TVariantType::IsSameType(const TVariantType& typeToCompare) const {
  1874. return GetUnderlyingType()->IsSameType(*typeToCompare.GetUnderlyingType());
  1875. }
  1876. size_t TVariantType::CalcHash() const {
  1877. return Data->CalcHash();
  1878. }
  1879. bool TVariantType::IsConvertableTo(const TVariantType& typeToCompare, bool ignoreTagged) const {
  1880. return GetUnderlyingType()->IsConvertableTo(*typeToCompare.GetUnderlyingType(), ignoreTagged);
  1881. }
  1882. TVariantType::TVariantType(TType* underlyingType, const TTypeEnvironment& env, bool validate)
  1883. : TType(EKind::Variant, env.GetTypeOfTypeLazy(), underlyingType->IsPresortSupported())
  1884. , Data(underlyingType)
  1885. {
  1886. if (validate) {
  1887. MKQL_ENSURE(underlyingType->IsTuple() || underlyingType->IsStruct(),
  1888. "Expected struct or tuple, but got: " << PrintNode(underlyingType, true));
  1889. if (underlyingType->IsTuple()) {
  1890. MKQL_ENSURE(AS_TYPE(TTupleType, underlyingType)->GetElementsCount() > 0, "Empty tuple is not allowed as underlying type for variant");
  1891. } else {
  1892. MKQL_ENSURE(AS_TYPE(TStructType, underlyingType)->GetMembersCount() > 0, "Empty struct is not allowed as underlying type for variant");
  1893. }
  1894. }
  1895. }
  1896. void TVariantType::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  1897. auto itemTypeIt = links.find(GetUnderlyingType());
  1898. if (itemTypeIt != links.end()) {
  1899. TNode* newNode = itemTypeIt->second;
  1900. Y_DEBUG_ABORT_UNLESS(GetUnderlyingType()->Equals(*newNode));
  1901. Data = static_cast<TType*>(newNode);
  1902. }
  1903. }
  1904. TNode* TVariantType::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  1905. auto newTypeNode = (TNode*)GetUnderlyingType()->GetCookie();
  1906. if (!newTypeNode) {
  1907. return const_cast<TVariantType*>(this);
  1908. }
  1909. return ::new(env.Allocate<TVariantType>()) TVariantType(static_cast<TType*>(newTypeNode), env, false);
  1910. }
  1911. void TVariantType::DoFreeze(const TTypeEnvironment& env) {
  1912. Y_UNUSED(env);
  1913. }
  1914. TVariantLiteral* TVariantLiteral::Create(TRuntimeNode item, ui32 index, TVariantType* type, const TTypeEnvironment& env) {
  1915. return ::new(env.Allocate<TVariantLiteral>()) TVariantLiteral(item, index, type);
  1916. }
  1917. TVariantLiteral::TVariantLiteral(TRuntimeNode item, ui32 index, TVariantType* type, bool validate)
  1918. : TNode(type)
  1919. , Item(item)
  1920. , Index(index)
  1921. {
  1922. Item.Freeze();
  1923. if (validate) {
  1924. MKQL_ENSURE(index < type->GetAlternativesCount(),
  1925. "Index out of range: " << index << " alt. count: " << type->GetAlternativesCount());
  1926. auto underlyingType = type->GetUnderlyingType();
  1927. if (underlyingType->IsTuple()) {
  1928. auto expectedType = AS_TYPE(TTupleType, underlyingType)->GetElementType(index);
  1929. MKQL_ENSURE(Item.GetStaticType()->IsSameType(*expectedType), "Wrong type of item");
  1930. } else {
  1931. auto expectedType = AS_TYPE(TStructType, underlyingType)->GetMemberType(index);
  1932. MKQL_ENSURE(Item.GetStaticType()->IsSameType(*expectedType), "Wrong type of item");
  1933. }
  1934. }
  1935. }
  1936. bool TVariantLiteral::Equals(const TVariantLiteral& nodeToCompare) const {
  1937. if (Index != nodeToCompare.GetIndex()) {
  1938. return false;
  1939. }
  1940. return Item.GetNode()->Equals(*nodeToCompare.GetItem().GetNode());
  1941. }
  1942. void TVariantLiteral::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  1943. auto typeIt = links.find(Type);
  1944. if (typeIt != links.end()) {
  1945. TNode* newNode = typeIt->second;
  1946. Y_DEBUG_ABORT_UNLESS(Type->Equals(*newNode));
  1947. Type = static_cast<TType*>(newNode);
  1948. }
  1949. auto itemIt = links.find(Item.GetNode());
  1950. if (itemIt != links.end()) {
  1951. TNode* newNode = itemIt->second;
  1952. Y_DEBUG_ABORT_UNLESS(Item.GetNode()->Equals(*newNode));
  1953. Item = TRuntimeNode(newNode, Item.IsImmediate());
  1954. }
  1955. }
  1956. TNode* TVariantLiteral::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  1957. auto newTypeNode = (TNode*)Type->GetCookie();
  1958. auto newItemNode = (TNode*)Item.GetNode()->GetCookie();
  1959. if (!newTypeNode && !newItemNode) {
  1960. return const_cast<TVariantLiteral*>(this);
  1961. }
  1962. return ::new(env.Allocate<TVariantLiteral>()) TVariantLiteral(
  1963. newItemNode ? TRuntimeNode(newItemNode, Item.IsImmediate()) : Item, Index,
  1964. newTypeNode ? static_cast<TVariantType*>(newTypeNode) : GetType(), false);
  1965. }
  1966. void TVariantLiteral::DoFreeze(const TTypeEnvironment& env) {
  1967. Y_UNUSED(env);
  1968. Item.Freeze();
  1969. }
  1970. TBlockType::TBlockType(TType* itemType, EShape shape, const TTypeEnvironment& env)
  1971. : TType(EKind::Block, env.GetTypeOfTypeLazy(), false)
  1972. , ItemType(itemType)
  1973. , Shape(shape)
  1974. {
  1975. }
  1976. TBlockType* TBlockType::Create(TType* itemType, EShape shape, const TTypeEnvironment& env) {
  1977. return ::new(env.Allocate<TBlockType>()) TBlockType(itemType, shape, env);
  1978. }
  1979. bool TBlockType::IsSameType(const TBlockType& typeToCompare) const {
  1980. return GetItemType()->IsSameType(*typeToCompare.GetItemType()) && Shape == typeToCompare.Shape;
  1981. }
  1982. size_t TBlockType::CalcHash() const {
  1983. return CombineHashes(ItemType->CalcHash(), IntHash((size_t)Shape));
  1984. }
  1985. bool TBlockType::IsConvertableTo(const TBlockType& typeToCompare, bool ignoreTagged) const {
  1986. return Shape == typeToCompare.Shape &&
  1987. GetItemType()->IsConvertableTo(*typeToCompare.GetItemType(), ignoreTagged);
  1988. }
  1989. void TBlockType::DoUpdateLinks(const THashMap<TNode*, TNode*>& links) {
  1990. const auto itemTypeIt = links.find(ItemType);
  1991. if (itemTypeIt != links.end()) {
  1992. auto* newNode = itemTypeIt->second;
  1993. Y_DEBUG_ABORT_UNLESS(ItemType->Equals(*newNode));
  1994. ItemType = static_cast<TType*>(newNode);
  1995. }
  1996. }
  1997. TNode* TBlockType::DoCloneOnCallableWrite(const TTypeEnvironment& env) const {
  1998. auto newTypeNode = (TNode*)ItemType->GetCookie();
  1999. if (!newTypeNode) {
  2000. return const_cast<TBlockType*>(this);
  2001. }
  2002. return ::new(env.Allocate<TBlockType>()) TBlockType(static_cast<TType*>(newTypeNode), Shape, env);
  2003. }
  2004. void TBlockType::DoFreeze(const TTypeEnvironment& env) {
  2005. Y_UNUSED(env);
  2006. }
  2007. bool IsNumericType(NUdf::TDataTypeId typeId) {
  2008. auto slot = NUdf::FindDataSlot(typeId);
  2009. return slot && NUdf::GetDataTypeInfo(*slot).Features & NUdf::NumericType;
  2010. }
  2011. bool IsCommonStringType(NUdf::TDataTypeId typeId) {
  2012. auto slot = NUdf::FindDataSlot(typeId);
  2013. return slot && NUdf::GetDataTypeInfo(*slot).Features & NUdf::StringType;
  2014. }
  2015. bool IsDateType(NUdf::TDataTypeId typeId) {
  2016. auto slot = NUdf::FindDataSlot(typeId);
  2017. return slot && NUdf::GetDataTypeInfo(*slot).Features & NUdf::DateType && *slot != NUdf::EDataSlot::Interval;
  2018. }
  2019. bool IsTzDateType(NUdf::TDataTypeId typeId) {
  2020. auto slot = NUdf::FindDataSlot(typeId);
  2021. return slot && NUdf::GetDataTypeInfo(*slot).Features & NUdf::TzDateType && *slot != NUdf::EDataSlot::Interval;
  2022. }
  2023. bool IsIntervalType(NUdf::TDataTypeId typeId) {
  2024. auto slot = NUdf::FindDataSlot(typeId);
  2025. return slot && NUdf::GetDataTypeInfo(*slot).Features & NUdf::TimeIntervalType;
  2026. }
  2027. EValueRepresentation GetValueRepresentation(NUdf::TDataTypeId type) {
  2028. switch (type) {
  2029. #define CASE_FOR(type, layout) \
  2030. case NUdf::TDataType<type>::Id:
  2031. KNOWN_FIXED_VALUE_TYPES(CASE_FOR)
  2032. #undef CASE_FOR
  2033. case NUdf::TDataType<NUdf::TDecimal>::Id:
  2034. case NUdf::TDataType<NUdf::TTzDate>::Id:
  2035. case NUdf::TDataType<NUdf::TTzDatetime>::Id:
  2036. case NUdf::TDataType<NUdf::TTzTimestamp>::Id:
  2037. return EValueRepresentation::Embedded;
  2038. default:
  2039. return EValueRepresentation::String;
  2040. }
  2041. }
  2042. EValueRepresentation GetValueRepresentation(const TType* type) {
  2043. switch (type->GetKind()) {
  2044. case TType::EKind::Data:
  2045. return GetValueRepresentation(static_cast<const TDataType*>(type)->GetSchemeType());
  2046. case TType::EKind::Optional:
  2047. return GetValueRepresentation(static_cast<const TOptionalType*>(type)->GetItemType());
  2048. case TType::EKind::Flow:
  2049. return GetValueRepresentation(static_cast<const TFlowType*>(type)->GetItemType());
  2050. case TType::EKind::Stream:
  2051. case TType::EKind::Struct:
  2052. case TType::EKind::Tuple:
  2053. case TType::EKind::Dict:
  2054. case TType::EKind::List:
  2055. case TType::EKind::Resource:
  2056. case TType::EKind::Block:
  2057. case TType::EKind::Callable:
  2058. case TType::EKind::EmptyList:
  2059. case TType::EKind::EmptyDict:
  2060. case TType::EKind::Multi:
  2061. return EValueRepresentation::Boxed;
  2062. case TType::EKind::Variant:
  2063. case TType::EKind::Void:
  2064. return EValueRepresentation::Any;
  2065. case TType::EKind::Null:
  2066. return EValueRepresentation::Embedded;
  2067. case TType::EKind::Pg:
  2068. return EValueRepresentation::Any;
  2069. case TType::EKind::Tagged:
  2070. return GetValueRepresentation(static_cast<const TTaggedType*>(type)->GetBaseType());
  2071. default:
  2072. Y_ABORT("Unsupported type.");
  2073. }
  2074. }
  2075. TArrayRef<TType* const> GetWideComponents(const TFlowType* type) {
  2076. if (type->GetItemType()->IsMulti()) {
  2077. return AS_TYPE(TMultiType, type->GetItemType())->GetElements();
  2078. }
  2079. return AS_TYPE(TTupleType, type->GetItemType())->GetElements();
  2080. }
  2081. TArrayRef<TType* const> GetWideComponents(const TStreamType* type) {
  2082. MKQL_ENSURE(RuntimeVersion > 35, "Wide stream is not supported in runtime version " << RuntimeVersion);
  2083. return AS_TYPE(TMultiType, type->GetItemType())->GetElements();
  2084. }
  2085. TArrayRef<TType *const> GetWideComponents(const TType* type) {
  2086. if (type->IsFlow()) {
  2087. const auto outputFlowType = AS_TYPE(TFlowType, type);
  2088. return GetWideComponents(outputFlowType);
  2089. }
  2090. if (type->IsStream()) {
  2091. const auto outputStreamType = AS_TYPE(TStreamType, type);
  2092. return GetWideComponents(outputStreamType);
  2093. }
  2094. MKQL_ENSURE(false, "Expect either flow or stream");
  2095. }
  2096. }
  2097. }